From fec44a5dfc182b7e6a84469ce73a343ae7dec61a Mon Sep 17 00:00:00 2001 From: Fabian Schiebel <52407375+fabianbs96@users.noreply.github.com> Date: Thu, 29 Feb 2024 16:58:24 +0100 Subject: [PATCH] Fix DebugLibDeps (#699) * Fix the option PHASAR_DEBUG_LIBDEPS to show unresolved functions in libraries * Silencing some warnings * Enable DEBUG_LIBDEPS for libphasar as well + don't include PhasarClang if BUILD_PHASAR_CLANG is OFF * Get rid of "extra semicolon" warning due to empty FRIEND_TEST macro * minor * Workaround incompatibility of DEBUG_LIBDEPS and ASAN * Update checkout version in CI to avoid deprecation warning * revert the swap --------- Co-authored-by: Martin Mory --- .github/workflows/ci.yml | 5 +- CMakeLists.txt | 14 +- cmake/phasar_macros.cmake | 6 +- config.h.in | 1 + include/phasar.h | 5 +- .../phasar/DataFlow/IfdsIde/FlowFunctions.h | 2 +- .../DataFlow/IfdsIde/IDETabulationProblem.h | 2 + .../PhasarLLVM/ControlFlow/LLVMBasedCFG.h | 9 +- .../PhasarLLVM/Pointer/LLVMPointsToUtils.h | 3 - .../Pointer/TypeGraphs/CachedTypeGraph.h | 18 +-- .../TypeHierarchy/LLVMTypeHierarchy.h | 8 -- .../phasar/PhasarLLVM/Utils/LLVMShorthands.h | 1 + lib/CMakeLists.txt | 9 +- lib/PhasarLLVM/ControlFlow/CMakeLists.txt | 2 +- lib/PhasarLLVM/ControlFlow/LLVMBasedCFG.cpp | 8 -- lib/PhasarLLVM/Passes/CMakeLists.txt | 2 +- .../Passes/GeneralStatisticsAnalysis.cpp | 4 +- lib/PhasarLLVM/Pointer/LLVMPointsToUtils.cpp | 20 --- lib/PhasarLLVM/Utils/LLVMShorthands.cpp | 132 ++++++++---------- tools/phasar-cli/CMakeLists.txt | 1 + .../TypeHierarchy/TypeGraphTest.cpp | 1 + 21 files changed, 102 insertions(+), 151 deletions(-) delete mode 100644 lib/PhasarLLVM/Pointer/LLVMPointsToUtils.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 67a32f1a5..b8dab4ed4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,12 +18,12 @@ jobs: - build: Debug flags: -DPHASAR_BUILD_DYNLIB=ON -DPHASAR_ENABLE_SANITIZERS=ON - build: Release - flags: -DPHASAR_ENABLE_DYNAMIC_LOG=OFF + flags: -DPHASAR_ENABLE_DYNAMIC_LOG=OFF -DPHASAR_DEBUG_LIBDEPS=ON -DBUILD_SHARED_LIBS=ON continue-on-error: false steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 0 submodules: recursive @@ -64,7 +64,6 @@ jobs: cmake .. \ -DCMAKE_BUILD_TYPE=${{ matrix.build }} \ -DBUILD_SWIFT_TESTS=ON \ - -DPHASAR_DEBUG_LIBDEPS=ON \ -DPHASAR_USE_Z3=ON \ ${{ matrix.flags }} \ -G Ninja diff --git a/CMakeLists.txt b/CMakeLists.txt index ab524715d..5669ead1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -158,15 +158,23 @@ option(PHASAR_ENABLE_CLANG_TIDY_DURING_BUILD "Run clang-tidy during build (defau option(PHASAR_BUILD_DOC "Build documentation" OFF) -option(PHASAR_DEBUG_LIBDEPS "Debug internal library dependencies (private linkage)" OFF) - -#option(BUILD_SHARED_LIBS "Build shared libraries (default is ON)" ON) option(PHASAR_BUILD_DYNLIB "Build one fat shared library. Requires BUILD_SHARED_LIBS to be turned OFF (default is OFF)" OFF) if(PHASAR_BUILD_DYNLIB AND BUILD_SHARED_LIBS) message(FATAL_ERROR "PHASAR_BUILD_DYNLIB is incompatible with BUILD_SHARED_LIBS") endif() +option(PHASAR_DEBUG_LIBDEPS "Debug internal library dependencies (private linkage)" OFF) +if (PHASAR_DEBUG_LIBDEPS) + if (NOT BUILD_SHARED_LIBS) + set(BUILD_SHARED_LIBS ON) + message("PHASAR_DEBUG_LIBDEPS only works for shared libraries, so set BUILD_SHARED_LIBS=ON") + endif() + if (PHASAR_ENABLE_SANITIZERS) + message(FATAL_ERROR "PHASAR_DEBUG_LIBDEPS is incompatible with ASAN (see https://clang.llvm.org/docs/AddressSanitizer.html#usage)") + endif() +endif () + option(PHASAR_ENABLE_PIC "Build Position-Independed Code" ON) if (PHASAR_ENABLE_PIC) set(CMAKE_POSITION_INDEPENDENT_CODE ON) diff --git a/cmake/phasar_macros.cmake b/cmake/phasar_macros.cmake index 2c9decf9a..8499a4905 100644 --- a/cmake/phasar_macros.cmake +++ b/cmake/phasar_macros.cmake @@ -192,13 +192,11 @@ function(add_phasar_library name) add_dependencies(${name} ${LLVM_COMMON_DEPENDS}) endif(LLVM_COMMON_DEPENDS) + target_link_libraries(${name} PUBLIC ${PHASAR_LIB_LINKS} phasar_interface ${PHASAR_LIB_LINK_PUBLIC}) if(PHASAR_DEBUG_LIBDEPS) - target_link_libraries(${name} PRIVATE ${PHASAR_LIB_LINKS}) - else() - target_link_libraries(${name} PUBLIC ${PHASAR_LIB_LINKS}) + target_link_libraries(${name} PRIVATE -Wl,-z,defs) endif() - target_link_libraries(${name} PUBLIC phasar_interface ${PHASAR_LIB_LINK_PUBLIC}) target_link_libraries(${name} PRIVATE ${PHASAR_LIB_LINK_PRIVATE}) phasar_link_llvm(${name} ${PHASAR_LIB_LLVM_LINK_COMPONENTS}) diff --git a/config.h.in b/config.h.in index d5df1dd0f..923329206 100644 --- a/config.h.in +++ b/config.h.in @@ -7,5 +7,6 @@ #cmakedefine PAMM_FULL #cmakedefine DYNAMIC_LOG +#cmakedefine BUILD_PHASAR_CLANG #endif /* PHASAR_CONFIG_CONFIG_H */ diff --git a/include/phasar.h b/include/phasar.h index d7ccfd4be..0444cf20f 100644 --- a/include/phasar.h +++ b/include/phasar.h @@ -17,11 +17,14 @@ #include "phasar/DB.h" #include "phasar/DataFlow.h" #include "phasar/Domain.h" -#include "phasar/PhasarClang.h" #include "phasar/PhasarLLVM.h" #include "phasar/PhasarPass.h" #include "phasar/Pointer.h" #include "phasar/TypeHierarchy.h" #include "phasar/Utils.h" +#ifdef BUILD_PHASAR_CLANG +#include "phasar/PhasarClang.h" +#endif + #endif // PHASAR_H diff --git a/include/phasar/DataFlow/IfdsIde/FlowFunctions.h b/include/phasar/DataFlow/IfdsIde/FlowFunctions.h index 24a511eca..83520ba07 100644 --- a/include/phasar/DataFlow/IfdsIde/FlowFunctions.h +++ b/include/phasar/DataFlow/IfdsIde/FlowFunctions.h @@ -135,7 +135,7 @@ Container makeContainer(Range &&Rng) { } return C; } -}; +} } // namespace detail //===----------------------------------------------------------------------===// diff --git a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h index d3c75c1ae..4cdc3610f 100644 --- a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h +++ b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h @@ -40,6 +40,7 @@ struct HasNoConfigurationType; template class AllTopFnProvider { public: + virtual ~AllTopFnProvider() = default; /// Returns an edge function that represents the top element of the analysis. virtual EdgeFunction allTopFunction() = 0; }; @@ -49,6 +50,7 @@ class AllTopFnProvider< AnalysisDomainTy, std::enable_if_t>> { public: + virtual ~AllTopFnProvider() = default; /// Returns an edge function that represents the top element of the analysis. virtual EdgeFunction allTopFunction() { return AllTop{}; diff --git a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h index 2c7ac54cf..a3134c713 100644 --- a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h +++ b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h @@ -18,8 +18,6 @@ #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instructions.h" -#include "nlohmann/json.hpp" - namespace llvm { class Function; } // namespace llvm @@ -28,6 +26,9 @@ namespace psr { class LLVMBasedCFG; class LLVMBasedBackwardCFG; +// Forward-declaration to avoid including LLVMShorthands.h here +bool isHeapAllocatingFunction(const llvm::Function *F) noexcept; + template <> struct CFGTraits { using n_t = const llvm::Instruction *; using f_t = const llvm::Function *; @@ -78,7 +79,9 @@ template class LLVMBasedCFGImpl : public CFGBase { [[nodiscard]] bool isFallThroughSuccessorImpl(n_t Inst, n_t Succ) const noexcept; [[nodiscard]] bool isBranchTargetImpl(n_t Inst, n_t Succ) const noexcept; - [[nodiscard]] bool isHeapAllocatingFunctionImpl(f_t Fun) const; + [[nodiscard]] bool isHeapAllocatingFunctionImpl(f_t Fun) const { + return psr::isHeapAllocatingFunction(Fun); + } [[nodiscard]] bool isSpecialMemberFunctionImpl(f_t Fun) const { return this->getSpecialMemberFunctionType(Fun) != SpecialMemberFunctionType{}; diff --git a/include/phasar/PhasarLLVM/Pointer/LLVMPointsToUtils.h b/include/phasar/PhasarLLVM/Pointer/LLVMPointsToUtils.h index 6ac25f29f..c1af0c3f2 100644 --- a/include/phasar/PhasarLLVM/Pointer/LLVMPointsToUtils.h +++ b/include/phasar/PhasarLLVM/Pointer/LLVMPointsToUtils.h @@ -10,7 +10,6 @@ #ifndef PHASAR_PHASARLLVM_POINTER_LLVMPOINTSTOUTILS_H_ #define PHASAR_PHASARLLVM_POINTER_LLVMPOINTSTOUTILS_H_ -#include "llvm/ADT/StringRef.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Value.h" @@ -29,8 +28,6 @@ namespace psr { !llvm::isa(V); } -[[nodiscard]] bool isHeapAllocatingFunction(const llvm::Function *Fun); - } // namespace psr #endif diff --git a/include/phasar/PhasarLLVM/Pointer/TypeGraphs/CachedTypeGraph.h b/include/phasar/PhasarLLVM/Pointer/TypeGraphs/CachedTypeGraph.h index 3759c704c..17efc1abb 100644 --- a/include/phasar/PhasarLLVM/Pointer/TypeGraphs/CachedTypeGraph.h +++ b/include/phasar/PhasarLLVM/Pointer/TypeGraphs/CachedTypeGraph.h @@ -27,8 +27,8 @@ #include #include -#ifndef FRIEND_TEST -#define FRIEND_TEST(TEST, CLASS) +#ifndef PSR_FRIEND_TEST +#define PSR_FRIEND_TEST(TEST, CLASS) #endif namespace llvm { @@ -75,13 +75,13 @@ class CachedTypeGraph : public TypeGraph { graph_t G; bool AlreadyVisited = false; - FRIEND_TEST(TypeGraphTest, AddType); - FRIEND_TEST(TypeGraphTest, AddLinkSimple); - FRIEND_TEST(TypeGraphTest, AddLinkWithSubs); - FRIEND_TEST(TypeGraphTest, AddLinkWithRecursion); - FRIEND_TEST(TypeGraphTest, ReverseTypePropagation); - FRIEND_TEST(TypeGraphTest, TypeAggregation); - FRIEND_TEST(TypeGraphTest, Merging); + PSR_FRIEND_TEST(TypeGraphTest, AddType) + PSR_FRIEND_TEST(TypeGraphTest, AddLinkSimple) + PSR_FRIEND_TEST(TypeGraphTest, AddLinkWithSubs) + PSR_FRIEND_TEST(TypeGraphTest, AddLinkWithRecursion) + PSR_FRIEND_TEST(TypeGraphTest, ReverseTypePropagation) + PSR_FRIEND_TEST(TypeGraphTest, TypeAggregation) + PSR_FRIEND_TEST(TypeGraphTest, Merging) vertex_t addType(const llvm::StructType *NewType); void reverseTypePropagation(const llvm::StructType *BaseStruct); diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h index 51b0e853f..c5b744e12 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h @@ -24,7 +24,6 @@ #include "boost/graph/adjacency_list.hpp" #include "boost/graph/graph_traits.hpp" -#include "nlohmann/json.hpp" #include #include @@ -33,10 +32,6 @@ #include #include -#ifndef FRIEND_TEST -#define FRIEND_TEST(TEST, CLASS) -#endif - namespace llvm { class Module; class StructType; @@ -135,9 +130,6 @@ class LLVMTypeHierarchy std::vector getVirtualFunctions(const llvm::Module &M, const llvm::StructType &Type); - FRIEND_TEST(LTHTest, GraphConstruction); - FRIEND_TEST(LTHTest, HandleLoadAndPrintOfNonEmptyGraph); - protected: void buildLLVMTypeHierarchy(const llvm::Module &M); diff --git a/include/phasar/PhasarLLVM/Utils/LLVMShorthands.h b/include/phasar/PhasarLLVM/Utils/LLVMShorthands.h index 21d2df136..11342497c 100644 --- a/include/phasar/PhasarLLVM/Utils/LLVMShorthands.h +++ b/include/phasar/PhasarLLVM/Utils/LLVMShorthands.h @@ -61,6 +61,7 @@ bool isIntegerLikeType(const llvm::Type *T) noexcept; * heap allocation function, e.g. new, new[], malloc, realloc or calloc. */ bool isAllocaInstOrHeapAllocaFunction(const llvm::Value *V) noexcept; +bool isHeapAllocatingFunction(const llvm::Function *F) noexcept; // TODO add description bool matchesSignature(const llvm::Function *F, const llvm::FunctionType *FType, diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index cbcfbaa01..e1cc7b0f6 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -8,13 +8,12 @@ add_subdirectory(Controller) add_subdirectory(Pointer) add_subdirectory(ControlFlow) if(BUILD_PHASAR_CLANG) + if(PHASAR_IN_TREE) + add_dependencies(phasar_interface intrinsics_gen) + endif() add_subdirectory(PhasarClang) endif() -# The fat lib relies on transitive dependencies... -set(PHASAR_DEBUG_LIBDEPS_SAVE ${PHASAR_DEBUG_LIBDEPS}) -set(PHASAR_DEBUG_LIBDEPS OFF) - if(PHASAR_BUILD_DYNLIB) set(PHASAR_DYNLIB_KIND SHARED) endif() @@ -52,5 +51,3 @@ add_phasar_library(phasar ${PHASAR_DYNLIB_KIND} Passes Demangle ) - -set(PHASAR_DEBUG_LIBDEPS ${PHASAR_DEBUG_LIBDEPS_SAVE}) diff --git a/lib/PhasarLLVM/ControlFlow/CMakeLists.txt b/lib/PhasarLLVM/ControlFlow/CMakeLists.txt index 162f9a6cf..ff8f27e28 100644 --- a/lib/PhasarLLVM/ControlFlow/CMakeLists.txt +++ b/lib/PhasarLLVM/ControlFlow/CMakeLists.txt @@ -6,8 +6,8 @@ add_phasar_library(phasar_llvm_controlflow LINKS phasar_llvm_pointer phasar_llvm_typehierarchy + phasar_llvm_utils phasar_db - phasar_utils phasar_controlflow LLVM_LINK_COMPONENTS diff --git a/lib/PhasarLLVM/ControlFlow/LLVMBasedCFG.cpp b/lib/PhasarLLVM/ControlFlow/LLVMBasedCFG.cpp index 1179bcb83..3eaf0f4fa 100644 --- a/lib/PhasarLLVM/ControlFlow/LLVMBasedCFG.cpp +++ b/lib/PhasarLLVM/ControlFlow/LLVMBasedCFG.cpp @@ -224,14 +224,6 @@ bool detail::LLVMBasedCFGImpl::isBranchTargetImpl( return false; } -template -bool detail::LLVMBasedCFGImpl::isHeapAllocatingFunctionImpl( - f_t Fun) const { - return llvm::StringSwitch(Fun->getName()) - .Cases("_Znwm", "_Znam", "malloc", "calloc", "realloc", true) - .Default(false); -} - template SpecialMemberFunctionType detail::LLVMBasedCFGImpl::getSpecialMemberFunctionTypeImpl( diff --git a/lib/PhasarLLVM/Passes/CMakeLists.txt b/lib/PhasarLLVM/Passes/CMakeLists.txt index 10c71117e..d7b8613ba 100644 --- a/lib/PhasarLLVM/Passes/CMakeLists.txt +++ b/lib/PhasarLLVM/Passes/CMakeLists.txt @@ -4,7 +4,7 @@ add_phasar_library(phasar_passes ${PASSES_SRC} LINKS - phasar_utils + phasar_llvm_utils LLVM_LINK_COMPONENTS Core diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp index 4ba840930..17facf8b0 100644 --- a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp +++ b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp @@ -9,7 +9,6 @@ #include "phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h" -#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/Logger.h" #include "phasar/Utils/NlohmannLogging.h" @@ -68,7 +67,6 @@ static void collectAllocatedTypes(const llvm::CallBase *CallSite, Set &Into) { llvm::AnalysisKey GeneralStatisticsAnalysis::Key; // NOLINT GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { PHASAR_LOG_LEVEL(INFO, "Running GeneralStatisticsAnalysis"); - LLVMBasedCFG CFG; Stats.ModuleName = M.getName().str(); for (auto &F : M) { ++Stats.Functions; @@ -182,7 +180,7 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { ++Stats.NumInlineAsm; } else if (const auto *CalleeFun = llvm::dyn_cast(CalledOp)) { - if (CFG.isHeapAllocatingFunction(CalleeFun)) { + if (isHeapAllocatingFunction(CalleeFun)) { // do not add allocas from llvm internal functions Stats.AllocaInstructions.insert(&I); ++Stats.AllocationSites; diff --git a/lib/PhasarLLVM/Pointer/LLVMPointsToUtils.cpp b/lib/PhasarLLVM/Pointer/LLVMPointsToUtils.cpp deleted file mode 100644 index 227b12a28..000000000 --- a/lib/PhasarLLVM/Pointer/LLVMPointsToUtils.cpp +++ /dev/null @@ -1,20 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2020 Philipp Schubert. - * All rights reserved. This program and the accompanying materials are made - * available under the terms of LICENSE.txt. - * - * Contributors: - * Philipp Schubert and others - *****************************************************************************/ - -#include "phasar/PhasarLLVM/Pointer/LLVMPointsToUtils.h" - -#include "llvm/ADT/StringSwitch.h" -#include "llvm/IR/Function.h" - -bool psr::isHeapAllocatingFunction(const llvm::Function *Fun) { - /// XXX: Consider using TargetLibraryInfo here - return llvm::StringSwitch(Fun->getName()) - .Cases("malloc", "calloc", "realloc", "_Znwm", "_Znam", "_ZnwPv", true) - .Default(false); -} diff --git a/lib/PhasarLLVM/Utils/LLVMShorthands.cpp b/lib/PhasarLLVM/Utils/LLVMShorthands.cpp index 1525668be..1fc03971e 100644 --- a/lib/PhasarLLVM/Utils/LLVMShorthands.cpp +++ b/lib/PhasarLLVM/Utils/LLVMShorthands.cpp @@ -17,18 +17,14 @@ #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Config/Configuration.h" -#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" -#include "phasar/Utils/Logger.h" #include "phasar/Utils/Utilities.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Bitcode/BitcodeWriter.h" -#include "llvm/IR/AbstractCallSite.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" -#include "llvm/IR/InstIterator.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" @@ -38,26 +34,14 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "boost/algorithm/string/trim.hpp" - -#include -#include #include #include #include -#include -#include using namespace std; using namespace psr; -namespace psr { - -/// Set of functions that allocate heap memory, e.g. new, new[], malloc. -const set HeapAllocationFunctions = {"_Znwm", "_Znam", "malloc", - "calloc", "realloc"}; - -bool isFunctionPointer(const llvm::Value *V) noexcept { +bool psr::isFunctionPointer(const llvm::Value *V) noexcept { if (V) { return V->getType()->isPointerTy() && V->getType()->getPointerElementType()->isFunctionTy(); @@ -65,7 +49,7 @@ bool isFunctionPointer(const llvm::Value *V) noexcept { return false; } -bool isIntegerLikeType(const llvm::Type *T) noexcept { +bool psr::isIntegerLikeType(const llvm::Type *T) noexcept { if (const auto *StructType = llvm::dyn_cast(T)) { return StructType->isPacked() && StructType->elements().size() == 1 && StructType->getElementType(0)->isIntegerTy(); @@ -73,24 +57,31 @@ bool isIntegerLikeType(const llvm::Type *T) noexcept { return false; } -bool isAllocaInstOrHeapAllocaFunction(const llvm::Value *V) noexcept { - if (V) { - if (llvm::isa(V)) { - return true; - } - if (const auto *CallSite = llvm::dyn_cast(V)) { - return CallSite->getCalledFunction() != nullptr && - HeapAllocationFunctions.count( - CallSite->getCalledFunction()->getName().str()); - } +bool psr::isAllocaInstOrHeapAllocaFunction(const llvm::Value *V) noexcept { + if (!V) { return false; } + + if (llvm::isa(V)) { + return true; + } + if (const auto *CallSite = llvm::dyn_cast(V)) { + return CallSite->getCalledFunction() && + isHeapAllocatingFunction(CallSite->getCalledFunction()); + } return false; } +bool psr::isHeapAllocatingFunction(const llvm::Function *Fun) noexcept { + return llvm::StringSwitch(Fun->getName()) + .Cases("_Znwm", "_Znam", "_ZnwPv", "malloc", "calloc", "realloc", true) + .Default(false); +} + // For C-style polymorphism we need to check whether a callee candidate would // be able to sanely access the formal argument. -bool isTypeMatchForFunctionArgument(llvm::Type *Actual, llvm::Type *Formal) { +static bool isTypeMatchForFunctionArgument(llvm::Type *Actual, + llvm::Type *Formal) { // First check for trivial type equality if (Actual == Formal) { return true; @@ -118,8 +109,8 @@ bool isTypeMatchForFunctionArgument(llvm::Type *Actual, llvm::Type *Formal) { return false; } -bool matchesSignature(const llvm::Function *F, const llvm::FunctionType *FType, - bool ExactMatch) { +bool psr::matchesSignature(const llvm::Function *F, + const llvm::FunctionType *FType, bool ExactMatch) { // FType->print(llvm::outs()); if (F == nullptr || FType == nullptr) { return false; @@ -142,8 +133,8 @@ bool matchesSignature(const llvm::Function *F, const llvm::FunctionType *FType, return false; } -bool matchesSignature(const llvm::FunctionType *FType1, - const llvm::FunctionType *FType2) { +bool psr::matchesSignature(const llvm::FunctionType *FType1, + const llvm::FunctionType *FType2) { if (FType1 == nullptr || FType2 == nullptr) { return false; } @@ -159,12 +150,12 @@ bool matchesSignature(const llvm::FunctionType *FType1, return false; } -llvm::ModuleSlotTracker &getModuleSlotTrackerFor(const llvm::Value *V) { +llvm::ModuleSlotTracker &psr::getModuleSlotTrackerFor(const llvm::Value *V) { const auto *M = getModuleFromVal(V); return ModulesToSlotTracker::getSlotTrackerForModule(M); } -std::string llvmIRToString(const llvm::Value *V) { +std::string psr::llvmIRToString(const llvm::Value *V) { if (!V) { return ""; } @@ -177,20 +168,7 @@ std::string llvmIRToString(const llvm::Value *V) { return llvm::StringRef(IRBuffer).ltrim().str(); } -std::string llvmTypeToString(const llvm::Type *T) { - // WARNING: Expensive function, cause is the T->print(RSO) - // (20ms on a medium size code (phasar without debug) - // 80ms on a huge size code (clang without debug), - // can be multiplied by times 3 to 5 if passes are enabled) - std::string IRBuffer; - llvm::raw_string_ostream RSO(IRBuffer); - T->print(RSO); - RSO.flush(); - boost::trim_left(IRBuffer); - return IRBuffer; -} - -std::string llvmIRToStableString(const llvm::Value *V) { +std::string psr::llvmIRToStableString(const llvm::Value *V) { if (!V) { return ""; } @@ -217,7 +195,7 @@ std::string llvmIRToStableString(const llvm::Value *V) { return IRBuffer; } -std::string llvmIRToShortString(const llvm::Value *V) { +std::string psr::llvmIRToShortString(const llvm::Value *V) { if (!V) { return ""; } @@ -236,7 +214,7 @@ std::string llvmIRToShortString(const llvm::Value *V) { return llvm::StringRef(IRBuffer).ltrim().str(); } -std::string llvmTypeToString(const llvm::Type *Ty, bool Shorten) { +std::string psr::llvmTypeToString(const llvm::Type *Ty, bool Shorten) { if (!Ty) { return ""; } @@ -253,15 +231,15 @@ std::string llvmTypeToString(const llvm::Type *Ty, bool Shorten) { return IRBuffer; } -void dumpIRValue(const llvm::Value *V) { +void psr::dumpIRValue(const llvm::Value *V) { llvm::outs() << llvmIRToString(V) << '\n'; } -void dumpIRValue(const llvm::Instruction *V) { +void psr::dumpIRValue(const llvm::Instruction *V) { llvm::outs() << llvmIRToString(V) << '\n'; } std::vector -globalValuesUsedinFunction(const llvm::Function *F) { +psr::globalValuesUsedinFunction(const llvm::Function *F) { std::vector GlobalsUsed; for (const auto &BB : *F) { for (const auto &I : BB) { @@ -276,7 +254,7 @@ globalValuesUsedinFunction(const llvm::Function *F) { return GlobalsUsed; } -std::string getMetaDataID(const llvm::Value *V) { +std::string psr::getMetaDataID(const llvm::Value *V) { if (const auto *Inst = llvm::dyn_cast(V)) { if (auto *Metadata = Inst->getMetadata(PhasarConfig::MetaDataKind())) { return llvm::cast(Metadata->getOperand(0)) @@ -305,12 +283,12 @@ bool LLVMValueIDLess::operator()(const llvm::Value *Lhs, return StringIDLess{}(LhsId, RhsId); } -int getFunctionArgumentNr(const llvm::Argument *Arg) { +int psr::getFunctionArgumentNr(const llvm::Argument *Arg) { return int(Arg->getArgNo()); } -const llvm::Argument *getNthFunctionArgument(const llvm::Function *F, - unsigned ArgNo) { +const llvm::Argument *psr::getNthFunctionArgument(const llvm::Function *F, + unsigned ArgNo) { if (ArgNo >= F->arg_size()) { return nullptr; } @@ -318,12 +296,12 @@ const llvm::Argument *getNthFunctionArgument(const llvm::Function *F, return F->getArg(ArgNo); } -const llvm::Instruction *getLastInstructionOf(const llvm::Function *F) { +const llvm::Instruction *psr::getLastInstructionOf(const llvm::Function *F) { return &F->back().back(); } -const llvm::Instruction *getNthInstruction(const llvm::Function *F, - unsigned Idx) { +const llvm::Instruction *psr::getNthInstruction(const llvm::Function *F, + unsigned Idx) { unsigned Current = 1; for (const auto &BB : *F) { for (const auto &I : BB) { @@ -338,13 +316,13 @@ const llvm::Instruction *getNthInstruction(const llvm::Function *F, } llvm::SmallVector -getAllExitPoints(const llvm::Function *F) { +psr::getAllExitPoints(const llvm::Function *F) { llvm::SmallVector Ret; appendAllExitPoints(F, Ret); return Ret; } -void appendAllExitPoints( +void psr::appendAllExitPoints( const llvm::Function *F, llvm::SmallVectorImpl &ExitPoints) { if (!F) { @@ -362,7 +340,7 @@ void appendAllExitPoints( } } -const llvm::Module *getModuleFromVal(const llvm::Value *V) { +const llvm::Module *psr::getModuleFromVal(const llvm::Value *V) { if (const auto *MA = llvm::dyn_cast(V)) { return MA->getParent() ? MA->getParent()->getParent() : nullptr; } @@ -391,12 +369,12 @@ const llvm::Module *getModuleFromVal(const llvm::Value *V) { return nullptr; } -std::string getModuleNameFromVal(const llvm::Value *V) { +std::string psr::getModuleNameFromVal(const llvm::Value *V) { const llvm::Module *M = getModuleFromVal(V); return M ? M->getModuleIdentifier() : " "; } -std::size_t computeModuleHash(llvm::Module *M, bool ConsiderIdentifier) { +std::size_t psr::computeModuleHash(llvm::Module *M, bool ConsiderIdentifier) { std::string SourceCode; if (ConsiderIdentifier) { llvm::raw_string_ostream RSO(SourceCode); @@ -413,7 +391,7 @@ std::size_t computeModuleHash(llvm::Module *M, bool ConsiderIdentifier) { return std::hash{}(SourceCode); } -std::size_t computeModuleHash(const llvm::Module *M) { +std::size_t psr::computeModuleHash(const llvm::Module *M) { std::string SourceCode; llvm::raw_string_ostream RSO(SourceCode); llvm::WriteBitcodeToFile(*M, RSO); @@ -421,8 +399,8 @@ std::size_t computeModuleHash(const llvm::Module *M) { return std::hash{}(SourceCode); } -const llvm::Instruction *getNthTermInstruction(const llvm::Function *F, - unsigned TermInstNo) { +const llvm::Instruction *psr::getNthTermInstruction(const llvm::Function *F, + unsigned TermInstNo) { unsigned Current = 1; for (const auto &BB : *F) { if (const llvm::Instruction *T = BB.getTerminator()) { @@ -435,8 +413,8 @@ const llvm::Instruction *getNthTermInstruction(const llvm::Function *F, return nullptr; } -const llvm::StoreInst *getNthStoreInstruction(const llvm::Function *F, - unsigned StoNo) { +const llvm::StoreInst *psr::getNthStoreInstruction(const llvm::Function *F, + unsigned StoNo) { unsigned Current = 1; for (const auto &BB : *F) { for (const auto &I : BB) { @@ -451,7 +429,7 @@ const llvm::StoreInst *getNthStoreInstruction(const llvm::Function *F, return nullptr; } -bool isGuardVariable(const llvm::Value *V) { +bool psr::isGuardVariable(const llvm::Value *V) { if (const auto *ConstBitcast = llvm::dyn_cast(V); ConstBitcast && ConstBitcast->isCast()) { V = ConstBitcast->getOperand(0); @@ -463,7 +441,8 @@ bool isGuardVariable(const llvm::Value *V) { return false; } -bool isStaticVariableLazyInitializationBranch(const llvm::BranchInst *Inst) { +bool psr::isStaticVariableLazyInitializationBranch( + const llvm::BranchInst *Inst) { if (Inst->isUnconditional()) { return false; } @@ -492,13 +471,14 @@ bool isStaticVariableLazyInitializationBranch(const llvm::BranchInst *Inst) { return false; } -bool isVarAnnotationIntrinsic(const llvm::Function *F) { +bool psr::isVarAnnotationIntrinsic(const llvm::Function *F) { static constexpr llvm::StringLiteral KVarAnnotationName( "llvm.var.annotation"); return F->getName() == KVarAnnotationName; } -llvm::StringRef getVarAnnotationIntrinsicName(const llvm::CallInst *CallInst) { +llvm::StringRef +psr::getVarAnnotationIntrinsicName(const llvm::CallInst *CallInst) { const int KPointerGlobalStringIdx = 1; auto *CE = llvm::cast( CallInst->getOperand(KPointerGlobalStringIdx)); @@ -578,5 +558,3 @@ void ModulesToSlotTracker::deleteMSTForModule(const llvm::Module *M) { MToST.erase(It); } } - -} // namespace psr diff --git a/tools/phasar-cli/CMakeLists.txt b/tools/phasar-cli/CMakeLists.txt index a20a7d6a8..a8276c347 100644 --- a/tools/phasar-cli/CMakeLists.txt +++ b/tools/phasar-cli/CMakeLists.txt @@ -37,6 +37,7 @@ target_link_libraries(phasar-cli phasar_llvm_pointer phasar_llvm phasar_llvm_typehierarchy + phasar_taintconfig ${PHASAR_STD_FILESYSTEM} ) diff --git a/unittests/PhasarLLVM/TypeHierarchy/TypeGraphTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/TypeGraphTest.cpp index 6fdc22e50..22a525223 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/TypeGraphTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/TypeGraphTest.cpp @@ -1,5 +1,6 @@ #include "gtest/gtest.h" // -- Need gtest for the FRIEND_TEST macro +#define PSR_FRIEND_TEST(TEST, CLASS) FRIEND_TEST(TEST, CLASS); #include "phasar/Config/Configuration.h" #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h"