Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion include/phasar/DB/ProjectIRDB.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>

#include <phasar/PhasarLLVM/Pointer/LLVMPointsToGraph.h>
#include <phasar/Utils/EnumFlags.h>

namespace llvm {
Expand Down
43 changes: 3 additions & 40 deletions include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class LLVMBasedICFG
};

/// Specify the type of graph to be used.
typedef boost::adjacency_list<boost::multisetS, boost::vecS,
typedef boost::adjacency_list<boost::vecS, boost::vecS,
boost::bidirectionalS, VertexProperties,
EdgeProperties>
bidigraph_t;
Expand All @@ -106,7 +106,7 @@ class LLVMBasedICFG
/// Maps function names to the corresponding vertex id.
std::unordered_map<const llvm::Function *, vertex_t> FunctionVertexMap;

void constructionWalker(const llvm::Function *F, Resolver *Res);
void constructionWalker(const llvm::Function *F, Resolver &Resolver);

struct dependency_visitor;

Expand Down Expand Up @@ -162,44 +162,7 @@ class LLVMBasedICFG
using LLVMBasedCFG::print; // tell the compiler we wish to have both prints
void print(std::ostream &OS = std::cout) const override;

// provide a VertexPropertyWrite to tell boost how to write a vertex
class CallGraphVertexWriter {
public:
CallGraphVertexWriter(const bidigraph_t &CGraph) : CGraph(CGraph) {}
template <class VertexOrEdge>
void operator()(std::ostream &out, const VertexOrEdge &v) const {
out << "[label=\"" << CGraph[v].getFunctionName() << "\"]";
}

private:
const bidigraph_t &CGraph;
};

// a function to conveniently create the vertex writer
CallGraphVertexWriter
makeCallGraphVertexWriter(const bidigraph_t &CGraph) const {
return CallGraphVertexWriter(CGraph);
}

// provide a EdgePropertyWrite to tell boost how to write an edge
class CallGraphEdgeWriter {
public:
CallGraphEdgeWriter(const bidigraph_t &CGraph) : CGraph(CGraph) {}
template <class VertexOrEdge>
void operator()(std::ostream &out, const VertexOrEdge &v) const {
out << "[label=\"" << CGraph[v].getCallSiteAsString() << "\"]";
}

private:
const bidigraph_t &CGraph;
};

// a function to conveniently create the edge writer
CallGraphEdgeWriter makeCallGraphEdgeWriter(const bidigraph_t &CGraph) const {
return CallGraphEdgeWriter(CGraph);
}

void printAsDot(std::ostream &OS = std::cout) const;
void printAsDot(std::ostream &OS = std::cout, bool printEdgeLabels = true) const;

void printInternalPTGAsDot(std::ostream &OS = std::cout) const;

Expand Down
1 change: 1 addition & 0 deletions lib/DB/ProjectIRDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include <boost/filesystem.hpp>

#include <phasar/Config/Configuration.h>
#include <phasar/DB/ProjectIRDB.h>
#include <phasar/PhasarLLVM/DataFlowSolver/IfdsIde/LLVMZeroValue.h>
#include <phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h>
Expand Down
134 changes: 85 additions & 49 deletions lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ LLVMBasedICFG::LLVMBasedICFG(ProjectIRDB &IRDB, CallGraphAnalysisType CGType,
PointsToGraph *PTG = PT->getPointsToGraph(F);
WholeModulePTG.mergeWith(PTG, F);
}
constructionWalker(F, Res.get());
constructionWalker(F, *Res.get());
}
REG_COUNTER("WM-PTG Vertices", WholeModulePTG.getNumOfVertices(),
PAMM_SEVERITY_LEVEL::Full);
Expand All @@ -166,29 +166,33 @@ LLVMBasedICFG::~LLVMBasedICFG() {
}

void LLVMBasedICFG::constructionWalker(const llvm::Function *F,
Resolver *Resolver) {
Resolver &Resolver) {
PAMM_GET_INSTANCE;
auto &lg = lg::get();
LOG_IF_ENABLE(BOOST_LOG_SEV(lg, DEBUG)
<< "Walking in function: " << F->getName().str());
if (VisitedFunctions.count(F) || F->isDeclaration()) {
if (F->isDeclaration() || !VisitedFunctions.insert(F).second ) {
LOG_IF_ENABLE(BOOST_LOG_SEV(lg, DEBUG)
<< "Function already visited or only declaration: "
<< F->getName().str());
return;
}
VisitedFunctions.insert(F);

// add a node for function F to the call graph (if not present already)
if (!FunctionVertexMap.count(F)) {
FunctionVertexMap[F] = boost::add_vertex(CallGraph);
CallGraph[FunctionVertexMap[F]] = VertexProperties(F);
vertex_t thisFunctionVertexDescriptor;
auto fvmItr = FunctionVertexMap.find(F);
if (fvmItr != FunctionVertexMap.end())
thisFunctionVertexDescriptor = fvmItr->second;
else {
thisFunctionVertexDescriptor = boost::add_vertex(VertexProperties(F), CallGraph);
FunctionVertexMap[F] = thisFunctionVertexDescriptor;
}

// iterate all instructions of the current function
for (auto &BB : *F) {
for (auto &I : BB) {
if (llvm::isa<llvm::CallInst>(I) || llvm::isa<llvm::InvokeInst>(I)) {
Resolver->preCall(&I);
Resolver.preCall(&I);

llvm::ImmutableCallSite cs(&I);
set<const llvm::Function *> possible_targets;
Expand All @@ -200,10 +204,11 @@ void LLVMBasedICFG::constructionWalker(const llvm::Function *F,
<< " " << llvmIRToString(cs.getInstruction()));
} else {
// still try to resolve the called function statically
const llvm::Value *v = cs.getCalledValue();
const llvm::Value *sv = v->stripPointerCasts();
if (sv->hasName() && IRDB.getFunction(sv->getName())) {
possible_targets.insert(IRDB.getFunction(sv->getName()));
const llvm::Value *sv = cs.getCalledValue()->stripPointerCasts();
const llvm::Function *valueFunction =
!sv->hasName() ? nullptr : IRDB.getFunction(sv->getName());
if (valueFunction) {
possible_targets.insert(valueFunction);
LOG_IF_ENABLE(BOOST_LOG_SEV(lg, DEBUG)
<< "Found static call-site: "
<< llvmIRToString(cs.getInstruction()));
Expand All @@ -215,9 +220,9 @@ void LLVMBasedICFG::constructionWalker(const llvm::Function *F,
<< " " << llvmIRToString(cs.getInstruction()));
// call the resolve routine
if (isVirtualFunctionCall(cs.getInstruction())) {
possible_targets = Resolver->resolveVirtualCall(cs);
possible_targets = Resolver.resolveVirtualCall(cs);
} else {
possible_targets = Resolver->resolveFunctionPointer(cs);
possible_targets = Resolver.resolveFunctionPointer(cs);
}
}
}
Expand All @@ -226,18 +231,19 @@ void LLVMBasedICFG::constructionWalker(const llvm::Function *F,
<< "Found " << possible_targets.size()
<< " possible target(s)");

Resolver->handlePossibleTargets(cs, possible_targets);
Resolver.handlePossibleTargets(cs, possible_targets);
// Insert possible target inside the graph and add the link with
// the current function
for (auto &possible_target : possible_targets) {
auto target = possible_target;
if (!FunctionVertexMap.count(target)) {
FunctionVertexMap[target] = boost::add_vertex(CallGraph);
CallGraph[FunctionVertexMap[target]] =
VertexProperties(possible_target);
vertex_t targetVertex;
auto targetFvmItr = FunctionVertexMap.find(possible_target);
if (targetFvmItr != FunctionVertexMap.end())
targetVertex = targetFvmItr->second;
else {
targetVertex = boost::add_vertex(VertexProperties(possible_target), CallGraph);
FunctionVertexMap[possible_target] = targetVertex;
}

boost::add_edge(FunctionVertexMap[F], FunctionVertexMap[target],
boost::add_edge(thisFunctionVertexDescriptor, targetVertex,
EdgeProperties(cs.getInstruction()), CallGraph);
}

Expand All @@ -246,9 +252,9 @@ void LLVMBasedICFG::constructionWalker(const llvm::Function *F,
constructionWalker(possible_target, Resolver);
}

Resolver->postCall(&I);
Resolver.postCall(&I);
} else {
Resolver->otherInst(&I);
Resolver.otherInst(&I);
}
}
}
Expand Down Expand Up @@ -446,23 +452,14 @@ LLVMBasedICFG::getLastInstructionOf(const string &name) {
}

void LLVMBasedICFG::mergeWith(const LLVMBasedICFG &other) {
// Copy other graph into this graph
typedef typename boost::property_map<bidigraph_t, boost::vertex_index_t>::type
index_map_t;
// For simple adjacency_list<> this type would be more efficient:
typedef typename boost::iterator_property_map<
typename std::vector<LLVMBasedICFG::vertex_t>::iterator, index_map_t,
LLVMBasedICFG::vertex_t, LLVMBasedICFG::vertex_t &>
IsoMap;
// For more generic graphs, one can try typedef std::map<vertex_t, vertex_t>
// IsoMap;
vector<LLVMBasedICFG::vertex_t> orig2copy_data(
boost::num_vertices(other.CallGraph));
IsoMap mapV = boost::make_iterator_property_map(
orig2copy_data.begin(), get(boost::vertex_index, other.CallGraph));
boost::copy_graph(other.CallGraph, CallGraph,
boost::orig_to_copy(mapV)); // means g1 += g2
// This vector hols the call-sites that are used to merge the whole-module
typedef bidigraph_t::vertex_descriptor vertex_t;
typedef std::map<vertex_t, vertex_t> vertex_map_t;
vertex_map_t oldToNewVertexMapping;
boost::associative_property_map<vertex_map_t> vertexMapWrapper(
oldToNewVertexMapping);
boost::copy_graph(other.CallGraph, CallGraph, boost::orig_to_copy(vertexMapWrapper));

// This vector holds the call-sites that are used to merge the whole-module
// points-to graphs
vector<pair<llvm::ImmutableCallSite, const llvm::Function *>> Calls;
vertex_iterator vi_v, vi_v_end, vi_u, vi_u_end;
Expand Down Expand Up @@ -494,12 +491,16 @@ void LLVMBasedICFG::mergeWith(const LLVMBasedICFG &other) {
}
}
}
// Update the FunctionVertexMap
FunctionVertexMap.clear();
for (boost::tie(vi_v, vi_v_end) = boost::vertices(CallGraph);
vi_v != vi_v_end; ++vi_v) {
FunctionVertexMap.insert(make_pair(CallGraph[*vi_v].F, *vi_v));

// Update the FunctionVertexMap:
for (const auto &otherValues : other.FunctionVertexMap) {
auto mappingIter = oldToNewVertexMapping.find(otherValues.second);
if (mappingIter != oldToNewVertexMapping.end()) {
FunctionVertexMap.insert(
make_pair(otherValues.first, mappingIter->second));
}
}

// Merge the already visited functions
VisitedFunctions.insert(other.VisitedFunctions.begin(),
other.VisitedFunctions.end());
Expand Down Expand Up @@ -535,9 +536,44 @@ void LLVMBasedICFG::print(ostream &OS) const {
}
}

void LLVMBasedICFG::printAsDot(std::ostream &OS) const {
boost::write_graphviz(OS, CallGraph, makeCallGraphVertexWriter(CallGraph),
makeCallGraphEdgeWriter(CallGraph));
namespace {
template <class graphType>
class VertexWriter {
public:
VertexWriter(const graphType &CGraph) : CGraph(CGraph) {}
template <class VertexOrEdge>
void operator()(std::ostream &out, const VertexOrEdge &v) const {
out << "[label=\"" << CGraph[v].getFunctionName() << "\"]";
}

private:
const graphType &CGraph;
};

template <class graphType>
class EdgeLabelWriter {
public:
EdgeLabelWriter(const graphType &CGraph) : CGraph(CGraph) {}
template <class VertexOrEdge>
void operator()(std::ostream &out, const VertexOrEdge &v) const {
out << "[label=\"" << CGraph[v].getCallSiteAsString() << "\"]";
}

private:
const graphType &CGraph;
};
}

void LLVMBasedICFG::printAsDot(std::ostream &OS, bool printEdgeLabels) const {
if (printEdgeLabels) {
boost::write_graphviz(OS, CallGraph,
VertexWriter<bidigraph_t>(CallGraph),
EdgeLabelWriter<bidigraph_t>(CallGraph));
} else {
boost::write_graphviz(OS, CallGraph,
VertexWriter<bidigraph_t>(CallGraph));

}
}

void LLVMBasedICFG::printInternalPTGAsDot(std::ostream &OS) const {
Expand Down
1 change: 1 addition & 0 deletions lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <llvm/IR/Instructions.h>
#include <llvm/IR/Module.h>

#include <phasar/Config/Configuration.h>
#include <phasar/DB/ProjectIRDB.h>
#include <phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h>
#include <phasar/Utils/GraphExtensions.h>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include <gtest/gtest.h>
#include <llvm/IR/InstIterator.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
#include <phasar/Config/Configuration.h>
#include <phasar/DB/ProjectIRDB.h>
#include <phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardCFG.h>
#include <phasar/Utils/LLVMShorthands.h>
Expand Down
3 changes: 3 additions & 0 deletions unittests/PhasarLLVM/ControlFlow/LLVMBasedCFGTest.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include <gtest/gtest.h>
#include <llvm/IR/InstIterator.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
#include <phasar/Config/Configuration.h>
#include <phasar/DB/ProjectIRDB.h>
#include <phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h>
#include <phasar/Utils/LLVMShorthands.h>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <gtest/gtest.h>

#include <phasar/Config/Configuration.h>
#include <phasar/DB/ProjectIRDB.h>
#include <phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h>
#include <phasar/Utils/LLVMShorthands.h>
Expand Down
1 change: 1 addition & 0 deletions unittests/PhasarLLVM/TypeHierarchy/TypeGraphTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <phasar/PhasarLLVM/Pointer/TypeGraphs/LazyTypeGraph.h>

#include <boost/graph/isomorphism.hpp>
#include <phasar/Config/Configuration.h>
#include <phasar/Utils/LLVMShorthands.h>
#include <phasar/Utils/Utilities.h>

Expand Down
3 changes: 3 additions & 0 deletions unittests/Utils/LLVMShorthandsTest.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#include <gtest/gtest.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
#include <phasar/Config/Configuration.h>
#include <phasar/DB/ProjectIRDB.h>
#include <phasar/Utils/LLVMShorthands.h>
#include <phasar/Utils/Utilities.h>
Expand Down