|
这学期在软件体系结构课上,被要求基于llvm-clang进行二次开发,查找项目中的全局变量,以及全局变量被调用的相关函数。本来传统思路是写一个checker来完成这个任务,但机缘巧合下了解到ASTMatcher可以作为一个很好的替代方案。由于与ASTMatcher相关的中文资料甚少,所以写下此博客,以记录本蒻的艰辛历程。由于是对学习过程加以记录,如果出现错误和纰漏还请见谅。 llvm-clang作为c/c++的编译器前端,基本工作是进行词法分析、语法分析,生成抽象语法树(AST)。此后将AST交由llvm作为后端进行处理,经由转换成中间代码、代码优化,最后交由与机器相关的底层模块生成相应的可执行文件。其中,抽象语法书AST作为语法分析的结果,包含了源代码所含有的全部信息。 针对具体需求而言,要查找全局变量,可以利用AST查找变量定义的节点(varDecl),且该节点不能有函数定义的父节点(functionDecl)。对于查找AST中节点的操作,clang的开发者提供了很便利的工具ASTMatcher以供使用。关于ASTMatcher的使用方法,请见官方文档如下: ASTMatcher使用向导:https://clang.llvm.org/docs/LibASTMatchersTutorial.html
ASTMatcher参考文档:https://clang.llvm.org/docs/LibASTMatchersReference.html#narrowing-matchers
在第一篇文档中详细的介绍了如何建立一个自己的ASTMatcher工具以供使用,第二篇文档中则包含了ASTMatcher节点匹配过程中可能用到的匹配规则。例如要匹配全局变量的定义节点,我的匹配器构建如下: DeclarationMatcher GlobalVarMatcher = varDecl( hasGlobalStorage(), unless(hasAncestor(functionDecl()))
).bind("gvar"); 在建立好匹配器之后,还需要继承MatchFinder::MatchCallback类,重写run方法,作用是确定匹配到节点之后如何使用。最后在main函数中调用写好的匹配器即可完成AST的节点匹配。 ……
项目进行中,有时间的时候就来更新吧~~~
/**************更新的分割线**************/ 最近有被同学问到如何在clang中去配置一个ASTMatcher,因为文档写的是在linux下的配置,和windows的配置方法有所出入,所以我把配置方法更新在下面:
1.在windows下下载llvm以及clang源码。具体步骤是下载llvm以及clang的源码,然后在clang/tools下git clone https://github.com/llvm-mirror/clang-tools-extra extra。即把clang-tools-extra的源码下载到clang/tools/extra目录下。 2.按照文档所述的步骤新建一个loop-convert文件夹,一个LoopConvert.cpp,并把CMakeLists.txt写好(详见第一篇文档)。这里的CMakeLists.txt包括loop-convert文件夹下的以及extra文件夹下的。写CMakeLists.txt的作用是给cmake工具构建工程提供依据。 3.cmake。在llvm根目录下新建一个build文件夹,在build文件夹下生成项目。我是用的visual studio 2017构建的项目,所以执行的指令是cmake visual studio 15 2017 ../lvm。针对其他的版本,可以通过cmake --help查看。
4.生成项目之后就可以用vs编译项目了,经过漫长的等待,编译完成后,大家就能在LLVM.sln下找到loop-convert子项目,即大家自己构建的ASTMatcher子项目。在之后的编码中,只需要生成loop-convert子项目即可(不是重新生成,是生成)。我自己的机器上每次生成用时不过数秒。 /************************我又是更新分割线**************************/ 有人问道cmakelist怎么写,官方文档里给的有点问题,和原llvm的配置有冲突,所以稍作修改: 这是loop-convert文件夹下的CMakeList.txt(文件名字改一下就好了。。。) set(LLVM_LINK_COMPONENTS support)
add_clang_executable(match-global-variable MatchGlobalVariable.cpp ) target_link_libraries(match-global-variable PRIVATE clangTooling clangBasic clangASTMatchers
) 在extra文件夹下的CMakeList.txt中加上一句add_subdirectory(match-global-variable)就好了。
|