├── .gitignore ├── README.md ├── example.png ├── pdg.cpp └── pdg.so /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LLVM-Program-Dependency-Graph-Generator 2 | 3 | ** Please make sure you have LLVM installed ** 4 | 5 | A pass that can generate PDG(in *.dot) for LLVM. 6 | 7 | As LLVM dosen't provide ways to generate Program Dependency Graph(PDG), and I need to use them in one of my project. 8 | I wrote this simple generation pass that can help generate PDG for a *.bc file. 9 | 10 | You can feel free to use it if you needed with simple insturctions like 11 | 12 | `"opt -load ./pdg.so -pdg < "filename" > /dev/null"` 13 | 14 | and it will generate a *.dot format output for each functions in the *.bc file 15 | like 16 | 17 |

18 | digraph add{
19 | 
20 | "a" -> "  %1 = getelementptr inbounds %struct.Node, %struct.Node* %a, i64 0, i32 0";
21 | "a" [ color = red ]
22 | "  %1 = getelementptr inbounds %struct.Node, %struct.Node* %a, i64 0, i32 0" -> "  %2 = load volatile %struct.Node*, %struct.Node** %1, align 8, !tbaa !2";
23 | "b" -> "  %3 = getelementptr inbounds %struct.Node, %struct.Node* %b, i64 0, i32 0";
24 | "b" [ color = red ]
25 | "  %2 = load volatile %struct.Node*, %struct.Node** %1, align 8, !tbaa !2" -> "  store volatile %struct.Node* %2, %struct.Node** %3, align 8, !tbaa !2";
26 | "  %3 = getelementptr inbounds %struct.Node, %struct.Node* %b, i64 0, i32 0" -> "  store volatile %struct.Node* %2, %struct.Node** %3, align 8, !tbaa !2";
27 | "b" -> "  %4 = getelementptr inbounds %struct.Node, %struct.Node* %b, i64 0, i32 1";
28 | "b" [ color = red ]
29 | "a" -> "  store volatile %struct.Node* %a, %struct.Node** %4, align 8, !tbaa !8";
30 | "a" [ color = red ]
31 | "  %4 = getelementptr inbounds %struct.Node, %struct.Node* %b, i64 0, i32 1" -> "  store volatile %struct.Node* %a, %struct.Node** %4, align 8, !tbaa !8";
32 | "  %1 = getelementptr inbounds %struct.Node, %struct.Node* %a, i64 0, i32 0" -> "  %5 = load volatile %struct.Node*, %struct.Node** %1, align 8, !tbaa !2";
33 | "  %5 = load volatile %struct.Node*, %struct.Node** %1, align 8, !tbaa !2" -> "  %6 = getelementptr inbounds %struct.Node, %struct.Node* %5, i64 0, i32 1";
34 | "b" -> "  store volatile %struct.Node* %b, %struct.Node** %6, align 8, !tbaa !8";
35 | "b" [ color = red ]
36 | "  %6 = getelementptr inbounds %struct.Node, %struct.Node* %5, i64 0, i32 1" -> "  store volatile %struct.Node* %b, %struct.Node** %6, align 8, !tbaa !8";
37 | "b" -> "  store volatile %struct.Node* %b, %struct.Node** %1, align 8, !tbaa !2";
38 | "b" [ color = red ]
39 | "  %1 = getelementptr inbounds %struct.Node, %struct.Node* %a, i64 0, i32 0" -> "  store volatile %struct.Node* %b, %struct.Node** %1, align 8, !tbaa !2";
40 | 
41 | }
42 | 
43 | 44 | and picture like below can be genertated by using *.dot drawer.( "dot" command under *.unix with graphviz) 45 | ![](example.png "example") 46 | 47 | 48 | -------------------------------------------------------------------------------- /example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DengMinghua/LLVM-Program-Dependency-Graph-Generator/faf85d4d4b0ff1df2d09cf066b8b8cbbab9ffda2/example.png -------------------------------------------------------------------------------- /pdg.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/ADT/Statistic.h" 2 | #include "llvm/IR/Function.h" 3 | #include "llvm/Pass.h" 4 | #include "llvm/Support/raw_ostream.h" 5 | using namespace llvm; 6 | 7 | #define DEBUG_TYPE "hello" 8 | 9 | namespace { 10 | struct Hello :public FunctionPass { 11 | static char ID; 12 | Hello():FunctionPass(ID){} 13 | virtual bool runOnFunction(Function &F) override { 14 | errs()<< "digraph "+F.getName() + "{\n"; 15 | errs() << "\n"; 16 | for(auto block = F.getBasicBlockList().begin();block != F.getBasicBlockList().end();block++) 17 | { 18 | for (auto inst = block->begin(); inst != block->end(); inst++) 19 | { 20 | for(Use &U:inst->operands()) 21 | { 22 | Value *v = U.get(); 23 | if(dyn_cast(v)) 24 | { 25 | errs() << "\"" << *dyn_cast(v) << "\"" << " -> " << "\"" << *inst << "\"" << ";\n"; 26 | } 27 | if (v->getName() != "") { 28 | errs() << "\"" << v->getName() << "\"" << " -> " << "\"" << *inst << "\"" << ";\n"; 29 | errs() << "\"" << v->getName() << "\"" << " [ color = red ]\n"; 30 | } 31 | } 32 | } 33 | } 34 | errs() << "\n}\n"; 35 | return false; 36 | } 37 | }; 38 | } 39 | 40 | char Hello::ID = 0; 41 | static RegisterPass X("pdg", "PDG Pass"); 42 | -------------------------------------------------------------------------------- /pdg.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DengMinghua/LLVM-Program-Dependency-Graph-Generator/faf85d4d4b0ff1df2d09cf066b8b8cbbab9ffda2/pdg.so --------------------------------------------------------------------------------