├── .gitignore
├── clang-cfg
├── CMakeLists.txt
└── pybind
│ ├── data_struct
│ ├── CMakeLists.txt
│ ├── Block.cpp
│ ├── CFG.cpp
│ ├── Block.h
│ ├── CFG.h
│ ├── AST.h
│ └── AST.cpp
│ ├── ast
│ ├── CMakeLists.txt
│ ├── ASTList.h
│ ├── ASTConsumerForAST.h
│ ├── ASTFrontendActionAST.h
│ ├── global.h
│ ├── ASTVisitorForAST.h
│ └── ASTVisitorForAST.cpp
│ ├── extend_cfg
│ ├── CMakeLists.txt
│ ├── CFGList.h
│ ├── global.h
│ ├── CFGFrontendAction.h
│ ├── ASTConsumerForCFG.h
│ ├── FunctionCFG.h
│ ├── ASTVisitorForCFG.h
│ ├── ASTVisitorForCFG.cpp
│ └── FunctionCFG.cpp
│ ├── CMakeLists.txt
│ ├── ParseHelper.h
│ ├── pybind.cpp
│ └── ParseHelper.cpp
├── .idea
├── clang-cfg.iml
├── vcs.xml
├── misc.xml
├── modules.xml
└── workspace.xml
├── cmake
└── external
│ ├── python.cmake
│ ├── pybind11.cmake
│ └── llvm.cmake
├── CMakeLists.txt
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | cmake-build-debug
2 | build
3 |
--------------------------------------------------------------------------------
/clang-cfg/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_subdirectory(pybind)
2 |
--------------------------------------------------------------------------------
/.idea/clang-cfg.iml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/data_struct/CMakeLists.txt:
--------------------------------------------------------------------------------
1 |
2 | ADD_LIBRARY(AST SHARED AST.h AST.cpp)
3 | ADD_LIBRARY(BLOCK SHARED Block.h Block.cpp)
4 | ADD_LIBRARY(CFG SHARED CFG.h CFG.cpp)
5 |
6 | ADD_DEPENDENCIES(CFG AST BLOCK)
7 | TARGET_LINK_LIBRARIES(CFG AST BLOCK)
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/ast/CMakeLists.txt:
--------------------------------------------------------------------------------
1 |
2 | ADD_LIBRARY(ast ASTFrontendActionAST.h ASTVisitorForAST.h ASTVisitorForAST.cpp ASTConsumerForAST.h ASTList.h global.h)
3 |
4 | TARGET_LINK_LIBRARIES(ast AST)
5 | SET_TARGET_PROPERTIES(ast PROPERTIES CXX_VISIBILITY_PRESET hidden)
6 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/data_struct/Block.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zzhzz on 2019-09-25.
3 | //
4 |
5 | #include "Block.h"
6 |
7 |
8 | namespace clang_cfg {
9 | void Block::add_ast(clang_cfg::AST ast) {
10 | this->content.push_back(ast);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/extend_cfg/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ADD_LIBRARY(extend_cfg global.h CFGFrontendAction.h ASTConsumerForCFG.h ASTVisitorForCFG.h ASTVisitorForCFG.cpp CFGList.h FunctionCFG.cpp FunctionCFG.h)
2 | TARGET_LINK_LIBRARIES(extend_cfg)
3 | SET_TARGET_PROPERTIES(extend_cfg PROPERTIES CXX_VISIBILITY_PRESET hidden)
4 |
--------------------------------------------------------------------------------
/cmake/external/python.cmake:
--------------------------------------------------------------------------------
1 |
2 | MESSAGE(STATUS "PY_VERSION = ${PY_VERSION}")
3 | FIND_PACKAGE(PythonInterp ${PY_VERSION} REQUIRED)
4 | FIND_PACKAGE(PythonLibs ${PY_VERSION} REQUIRED)
5 |
6 | ADD_LIBRARY(python STATIC IMPORTED GLOBAL)
7 | SET_PROPERTY(TARGET python PROPERTY IMPORTED_LOCATION ${PYTHON_LIBRARIES})
8 |
9 | INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIR})
10 |
11 |
12 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/data_struct/CFG.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zzhzz on 2019-09-25.
3 | //
4 |
5 | #include "CFG.h"
6 |
7 | namespace clang_cfg {
8 |
9 | void CFG::add_block(clang_cfg::Block block) {
10 | this->block_list.push_back(block);
11 | }
12 |
13 | void CFG::add_edge(int u, int v, int type) {
14 | this->edges.push_back(std::make_pair(std::make_pair(u, v), type));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/ast/ASTList.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zzhzz on 2019/11/15.
3 | //
4 |
5 | #pragma once
6 |
7 | #include "global.h"
8 | #include "data_struct/AST.h"
9 |
10 | namespace clang_cfg{
11 | class ASTList {
12 | public:
13 | static ASTList& getInst() {
14 | static ASTList inst;
15 | return inst;
16 | }
17 | vector vecs;
18 | private:
19 | ASTList() = default;
20 | };
21 |
22 | }
23 |
24 |
25 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/extend_cfg/CFGList.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zzhzz on 2019-09-26.
3 | //
4 |
5 | #pragma once
6 |
7 | #include "global.h"
8 | #include "data_struct/CFG.h"
9 |
10 | namespace clang_cfg{
11 | class CFGList {
12 | public:
13 | static CFGList& getInst() {
14 | static CFGList inst;
15 | return inst;
16 | }
17 | vector> vecs;
18 | private:
19 | CFGList() = default;
20 | };
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/cmake/external/pybind11.cmake:
--------------------------------------------------------------------------------
1 | INCLUDE(ExternalProject)
2 |
3 | SET(PYBIND_SOURCE_DIR ${THIRD_PARTY_PATH}/pybind11)
4 | INCLUDE_DIRECTORIES(${PYBIND_SOURCE_DIR}/build/include)
5 |
6 | ExternalProject_Add(
7 | extern_pybind
8 | GIT_REPOSITORY "https://github.com/pybind/pybind11.git"
9 | GIT_TAG "v2.2.4"
10 | PREFIX ${PYBIND_SOURCE_DIR}
11 | CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PYBIND_SOURCE_DIR}/build
12 | )
13 |
14 | ADD_LIBRARY(pybind INTERFACE)
15 | ADD_DEPENDENCIES(pybind extern_pybind)
--------------------------------------------------------------------------------
/clang-cfg/pybind/data_struct/Block.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zzhzz on 2019-09-25.
3 | //
4 | #pragma once
5 |
6 | #ifndef CLANG_CFG_BLOCK_H
7 | #define CLANG_CFG_BLOCK_H
8 |
9 | #include
10 | #include
11 |
12 | #include "AST.h"
13 |
14 | using std::vector;
15 |
16 | namespace clang_cfg{
17 | class Block {
18 | public:
19 | int start_lineno, end_lineno;
20 | void add_ast(AST ast);
21 | vector content;
22 | };
23 |
24 | }
25 |
26 |
27 | #endif //CLANG_CFG_BLOCK_H
28 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ADD_SUBDIRECTORY(extend_cfg)
2 | ADD_SUBDIRECTORY(ast)
3 | ADD_SUBDIRECTORY(data_struct)
4 |
5 | ADD_LIBRARY(ParseHelper ParseHelper.cpp ParseHelper.h)
6 |
7 | PYTHON_ADD_MODULE(clang_cfg pybind.cpp)
8 |
9 | TARGET_LINK_LIBRARIES(clang_cfg extend_cfg ast CFG ParseHelper)
10 |
11 | TARGET_LINK_LIBRARIES(clang_cfg ${CLANG_LIBS} ${LLVM_LIBS})
12 |
13 | IF(APPLE)
14 | LIST(APPEND SYSTEM_LIBS pthread dl z curses m xml2)
15 | ELSEIF(UNIX)
16 | LIST(APPEND SYSTEM_LIBS pthread dl tinfo z)
17 | ENDIF()
18 |
19 | TARGET_LINK_LIBRARIES(clang_cfg ${SYSTEM_LIBS})
20 | SET_TARGET_PROPERTIES(clang_cfg PROPERTIES CXX_VISIBILITY_PRESET hidden)
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/ast/ASTConsumerForAST.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zzhzz on 2019/11/15.
3 | //
4 |
5 | #pragma once
6 |
7 | #include "global.h"
8 | #include "ASTVisitorForAST.h"
9 | #include "ASTList.h"
10 |
11 | #include
12 |
13 | namespace clang_cfg{
14 |
15 | using std::vector;
16 | class ASTConsumerForAST : public ASTConsumer {
17 | public:
18 | ASTConsumerForAST(ASTContext& ctx, Rewriter& rewriter) : visitor(ctx, rewriter) {}
19 |
20 | void HandleTranslationUnit(ASTContext& context) override {
21 | visitor.TraverseDecl(context.getTranslationUnitDecl());
22 | }
23 |
24 | private:
25 | ASTVisitorForAST visitor;
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/data_struct/CFG.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zzhzz on 2019-09-25.
3 | //
4 |
5 | #pragma once
6 |
7 | #ifndef CLANG_CFG_CFG_H
8 | #define CLANG_CFG_CFG_H
9 |
10 | #include
11 | #include
12 |
13 | #include "Block.h"
14 | #include "AST.h"
15 |
16 |
17 | namespace clang_cfg {
18 | using std::vector;
19 | using std::pair;
20 | using std::string;
21 |
22 | class CFG{
23 | public:
24 | void add_block(Block block);
25 | void add_edge(int u, int v, int type);
26 | vector,int>> edges;
27 | vector block_list;
28 | vector call_list;
29 | string func_name;
30 | };
31 | }
32 |
33 | #endif //CLANG_CFG_CFG_H
34 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/ast/ASTFrontendActionAST.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zzhzz on 2019/11/14.
3 | //
4 |
5 | #pragma once
6 |
7 | #include "global.h"
8 | #include "ASTConsumerForAST.h"
9 |
10 | #include
11 |
12 | namespace clang_cfg
13 | {
14 | using std::vector;
15 | class ASTFrontendActionAST : public ASTFrontendAction {
16 | public:
17 | std::unique_ptr CreateASTConsumer(CompilerInstance& CI, StringRef file) override {
18 | rewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
19 | return std::make_unique(CI.getASTContext(), rewriter);
20 | }
21 | private:
22 | Rewriter rewriter;
23 |
24 | };
25 | }
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/ast/global.h:
--------------------------------------------------------------------------------
1 | //
2 | //
3 | // Created by zzhzz on 2019-09-26.
4 | //
5 | #pragma once
6 |
7 | #include
8 | #include
9 |
10 | #include
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include "data_struct/AST.h"
23 |
24 | namespace clang_cfg {
25 | using namespace clang;
26 | using namespace clang::driver;
27 | using namespace clang::tooling;
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/extend_cfg/global.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zzhzz on 2019-09-26.
3 | //
4 | #pragma once
5 |
6 | #include
7 | #include
8 |
9 | #include
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include "ParseHelper.h"
23 | #include "data_struct/CFG.h"
24 |
25 | namespace clang_cfg {
26 | using namespace clang;
27 | using namespace clang::driver;
28 | using namespace clang::tooling;
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/ast/ASTVisitorForAST.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zzhzz on 2019/11/14.
3 | //
4 |
5 | #ifndef CLANG_CFG_ASTVISITORFORAST_H
6 | #define CLANG_CFG_ASTVISITORFORAST_H
7 |
8 | #include "global.h"
9 | #include "ASTList.h"
10 |
11 | #include
12 |
13 | namespace clang_cfg{
14 | using std::vector;
15 | using namespace clang;
16 | using namespace clang::tooling;
17 |
18 | class ASTVisitorForAST : public RecursiveASTVisitor {
19 | public:
20 | ASTVisitorForAST(ASTContext& ctx, Rewriter& rewriter) :
21 | context(ctx), rewriter(rewriter) { };
22 |
23 | bool VisitTranslationUnitDecl(TranslationUnitDecl* decl);
24 |
25 | private:
26 | ASTContext& context;
27 | Rewriter& rewriter;
28 | };
29 | }
30 |
31 | #endif //CLANG_CFG_ASTVISITORFORAST_H
32 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/extend_cfg/CFGFrontendAction.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zzhzz on 2019-09-26.
3 | //
4 | #pragma once
5 |
6 | #ifndef CLANG_CFG_CFGFRONTENDACTION_H
7 | #define CLANG_CFG_CFGFRONTENDACTION_H
8 |
9 | #include "global.h"
10 | #include "ASTConsumerForCFG.h"
11 |
12 | #include
13 |
14 | namespace clang_cfg
15 | {
16 | using std::vector;
17 | class CFGFrontendAction : public ASTFrontendAction{
18 | public:
19 | std::unique_ptr CreateASTConsumer(CompilerInstance& CI, StringRef file) override {
20 | rewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
21 | return std::make_unique(CI.getASTContext(), rewriter);
22 | }
23 | private:
24 | Rewriter rewriter;
25 |
26 | };
27 | }
28 |
29 |
30 |
31 | #endif //CLANG_CFG_CFGFRONTENDACTION_H
32 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | CMAKE_MINIMUM_REQUIRED(VERSION 3.6)
2 | PROJECT(Clang-CFG)
3 | SET(CMAKE_C_COMPILER gcc)
4 | SET(CMAKE_CXX_COMPILER g++)
5 | SET(CMAKE_CXX_STANDARD 14)
6 |
7 | SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
8 | SET(THIRD_PARTY_PATH "${CMAKE_BINARY_DIR}/third_party" CACHE STRING
9 | "A path setting third party libraries download & build directories")
10 |
11 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -frtti -fPIC")
12 |
13 | OPTION(PY_VERSION "Specify python version" ${PY_VERSION})
14 |
15 | IF(NOT PY_VERSION)
16 | SET(PY_VERSION 3.6)
17 | ENDIF()
18 |
19 | SET(THIRD_PARTY_BUILD_TYPE Release)
20 |
21 | INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/clang-cfg/pybind)
22 |
23 | INCLUDE(external/python)
24 | INCLUDE(external/pybind11)
25 | INCLUDE(external/llvm)
26 |
27 | LINK_LIBRARIES(${PYTHON_LIBRARIES} ${CLANG_LIBS} ${LLVM_LIBS})
28 |
29 | ADD_SUBDIRECTORY(clang-cfg)
30 |
31 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/extend_cfg/ASTConsumerForCFG.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zzhzz on 2019-09-26.
3 | //
4 | #pragma once
5 |
6 | #ifndef CLANG_CFG_ASTCONSUMERFORCFG_H
7 | #define CLANG_CFG_ASTCONSUMERFORCFG_H
8 |
9 | #include "global.h"
10 | #include "ASTVisitorForCFG.h"
11 | #include "CFGList.h"
12 |
13 | #include
14 |
15 | namespace clang_cfg{
16 |
17 | using std::vector;
18 | class ASTConsumerForCFG : public ASTConsumer {
19 | public:
20 | ASTConsumerForCFG(ASTContext& ctx, Rewriter& rewriter) : visitor(ctx, rewriter) {}
21 |
22 | void HandleTranslationUnit(ASTContext& context) override {
23 | CFGList& list = CFGList::getInst();
24 | list.vecs.emplace_back(vector());
25 | visitor.TraverseDecl(context.getTranslationUnitDecl());
26 | }
27 |
28 | private:
29 | ASTVisitorForCFG visitor;
30 | };
31 | }
32 |
33 | #endif //CLANG_CFG_ASTCONSUMERFORCFG_H
34 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/ParseHelper.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zzhzz on 2019-09-26.
3 | //
4 |
5 | #pragma once
6 |
7 | #ifndef CLANG_CFG_PARSEHELPER_H
8 | #define CLANG_CFG_PARSEHELPER_H
9 |
10 |
11 | #include
12 | #include
13 |
14 | #include "data_struct/AST.h"
15 | #include "extend_cfg/global.h"
16 |
17 | namespace clang_cfg {
18 | using namespace clang;
19 | using namespace clang::tooling;
20 | using std::string;
21 | using std::set;
22 | class ParseHelper {
23 | public:
24 | static bool isInSystem(ASTContext& context, const FunctionDecl* decl);
25 | static bool canIncludeInGraph(Decl* decl);
26 | static bool canBeCallerInGraph(Decl* decl);
27 | static string getVarName(const Expr* expr);
28 | static Decl* getDeclFromCall(CallExpr* callExpr);
29 | static void type_simplify(AST& ast, int uid, string &type);
30 | };
31 | }
32 |
33 |
34 | #endif //CLANG_CFG_PARSEHELPER_H
35 |
--------------------------------------------------------------------------------
/clang-cfg/pybind/extend_cfg/FunctionCFG.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zzhzz on 2019-09-26.
3 | //
4 | #pragma once
5 |
6 | #ifndef CLANG_CFG_FUNCTIONCFG_H
7 | #define CLANG_CFG_FUNCTIONCFG_H
8 |
9 | #include "global.h"
10 | #include "CFGList.h"
11 |
12 | namespace clang_cfg {
13 | using namespace clang;
14 | using namespace llvm;
15 | using std::string;
16 |
17 | class FunctionCFG {
18 | public:
19 | typedef FunctionCFG* FunctionRecord;
20 | FunctionCFG(Decl* d) : decl(d) {}
21 | string getNameAsString() const;
22 |
23 | void addFunction(FunctionRecord record) {
24 | if(std::find(functions.begin(), functions.end(), record) != functions.end()) return;
25 | functions.push_back(record);
26 | }
27 | void getCFG(ASTContext& ctx);
28 | AST transToAST(Stmt* stmt, ASTContext& ctx);
29 | private:
30 | Decl* decl;
31 | SmallVector functions;
32 | };
33 | }
34 |
35 |
36 | #endif //CLANG_CFG_FUNCTIONCFG_H
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Clang-CFG: A tool based on Clang LibTooling
2 |
3 | ## Introduction
4 | The tool is based on clang libtooling technology, used to generate control-flow-graph for C/C++ code.
5 |
6 | The tool is a static python library, which could be invoke directly in python.
7 |
8 |
9 | ## Usage
10 |
11 | * Firstly, download the repository
12 | * use `cd clang-cfg` change into the directory
13 | * use `mkdir build` create a directory for binary files
14 | * use `cd build` change into the binary directory
15 | * use `cmake ..` to create MakeFiles
16 | * use `make` to build the project
17 |
18 | For an alpha version, I haven't provide python wrapper for the project and shoud be import directly
19 |
20 | * run `cd build/clang-cfg/pybind` change into the directory of static library
21 | * run `python -c "import clang_cfg" to test
22 |
23 | ## Tips
24 |
25 | * This project based on llvm, it will take long time to download and build llvm as a third party project
26 | * This project based on pybind11, which needs to open `-frtti` option of compiler. The default compile option of llvm doesn't open it.
--------------------------------------------------------------------------------
/clang-cfg/pybind/data_struct/AST.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zzhzz on 2019-09-23.
3 | //
4 |
5 | #pragma once
6 |
7 | #ifndef CLANG_CFG_EXTENDAST_H
8 | #define CLANG_CFG_EXTENDAST_H
9 |
10 | #include
11 | #include
12 | #include
13 | #include