AST info parser for edk2 - shijunjing/edk2 GitHub Wiki
Edk2 AST parser based on Clang LibTooling and LibASTMatchers https://github.com/shijunjing/edk2/wiki/Try-tutorial-for-building-tools-using-LibTooling-and-LibASTMatchers
jshi19@ub2-uefi-b01:~/llvm/llvm-project/LibASTMatchersTutorial$ git status
On branch edk2-metrics
jshi19@ub2-uefi-b01:~/llvm/llvm-project/LibASTMatchersTutorial$ cmake -G Ninja ../llvm -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra" -DCMAKE_BUILD_TYPE="MinSizeRel" -DLLVM_TARGETS_TO_BUILD="X86" -DCMAKE_INSTALL_PREFIX=../minsizerelinstall/ -DLLVM_ENABLE_Z3_SOLVER=OFF -DLLVM_CCACHE_BUILD=ON
jshi19@ub2-uefi-b01:~/llvm/llvm-project/LibASTMatchersTutorial$ ninja edk2-ast-parser
jshi19@ub2-uefi-b01:~/llvm/llvm-project/LibASTMatchersTutorial$ bin/edk2-ast-parser ~/llvm/wrongcode/loop-convert/simple-loops.cc
Error while trying to load a compilation database:
Could not auto-detect compilation database for file "/home/jshi19/llvm/wrongcode/loop-convert/simple-loops.cc"
No compilation database found in /home/jshi19/llvm/wrongcode/loop-convert or any parent directory
fixed-compilation-database: Error while opening fixed database: No such file or directory
json-compilation-database: Error while opening JSON database: No such file or directory
Running without flags.
FunctionPrinter is called:0times
/usr/include/x86_64-linux-gnu/bits/libio.h:_IO_cookie_init:380:13
FunctionPrinter is called:1times
... ...
/usr/include/stdio.h:ftrylockfile:844:12
FunctionPrinter is called:117times
/usr/include/stdio.h:funlockfile:847:13
FunctionPrinter is called:118times
/home/jshi19/llvm/wrongcode/loop-convert/simple-loops.cc:DMA_Read:6:6
FunctionDecl 0x55fd1926a680 </home/jshi19/llvm/wrongcode/loop-convert/simple-loops.cc:6:1, line:18:1> line:6:6 used DMA_Read 'void (void *, int)'
|-ParmVarDecl 0x55fd1926a520 <col:15, col:22> col:22 buffer 'void *'
|-ParmVarDecl 0x55fd1926a5a0 <col:30, col:34> col:34 used size 'int'
`-CompoundStmt 0x55fd1926c028 <col:39, line:18:1>
|-DeclStmt 0x55fd1926a870 <line:8:3, line:4:35>
| `-VarDecl 0x55fd1926a748 <line:8:3, line:4:21> line:8:7 used datalen 'int' cinit
| `-ImplicitCastExpr 0x55fd1926a858 <col:17, line:4:21> 'int' <LValueToRValue>
| `-UnaryOperator 0x55fd1926a840 <line:8:17, line:4:21> 'volatile int' lvalue prefix '*' cannot overflow
| `-CStyleCastExpr 0x55fd1926a818 <line:8:18, line:4:21> 'volatile int *' <IntegralToPointer>
| `-IntegerLiteral 0x55fd1926a7b0 <col:21> 'long' 140729166944016
|-NullStmt 0x55fd1926a888 <line:8:44>
|-CallExpr 0x55fd1926aa48 <line:9:3, col:34> 'int'
| |-ImplicitCastExpr 0x55fd1926aa30 <col:3> 'int (*)(const char *__restrict, ...)' <FunctionToPointerDecay>
| | `-DeclRefExpr 0x55fd1926a9a8 <col:3> 'int (const char *__restrict, ...)' lvalue Function 0x55fd192584c0 'printf' 'int (const char *__restrict, ...)'
| |-ImplicitCastExpr 0x55fd1926aa78 <col:10> 'const char *' <ArrayToPointerDecay>
| | `-StringLiteral 0x55fd1926a960 <col:10> 'const char [13]' lvalue "datalen=%d \n"
| `-ImplicitCastExpr 0x55fd1926aa90 <col:27> 'int' <LValueToRValue>
| `-DeclRefExpr 0x55fd1926a988 <col:27> 'int' lvalue Var 0x55fd1926a748 'datalen' 'int'
`-IfStmt 0x55fd1926c000 <line:10:3, line:17:3> has_else
|-BinaryOperator 0x55fd1926ab18 <line:10:6, col:14> 'bool' '>='
| |-ImplicitCastExpr 0x55fd1926aae8 <col:6> 'int' <LValueToRValue>
| | `-DeclRefExpr 0x55fd1926aaa8 <col:6> 'int' lvalue ParmVar 0x55fd1926a5a0 'size' 'int'
| `-ImplicitCastExpr 0x55fd1926ab00 <col:14> 'int' <LValueToRValue>
| `-DeclRefExpr 0x55fd1926aac8 <col:14> 'int' lvalue Var 0x55fd1926a748 'datalen' 'int'
|-CompoundStmt 0x55fd1926ae20 <col:22, line:14:3>
| |-CallExpr 0x55fd1926ac68 <line:11:5, col:33> 'int'
| | |-ImplicitCastExpr 0x55fd1926ac50 <col:5> 'int (*)(const char *__restrict, ...)' <FunctionToPointerDecay>
| | | `-DeclRefExpr 0x55fd1926ac30 <col:5> 'int (const char *__restrict, ...)' lvalue Function 0x55fd192584c0 'printf' 'int (const char *__restrict, ...)'
| | `-ImplicitCastExpr 0x55fd1926ac90 <col:12> 'const char *' <ArrayToPointerDecay>
| | `-StringLiteral 0x55fd1926ac00 <col:12> 'const char [19]' lvalue "Start reading DMA\n"
| `-CallExpr 0x55fd1926ade0 <line:13:5, col:41> 'int'
| |-ImplicitCastExpr 0x55fd1926adc8 <col:5> 'int (*)(const char *__restrict, ...)' <FunctionToPointerDecay>
| | `-DeclRefExpr 0x55fd1926ada8 <col:5> 'int (const char *__restrict, ...)' lvalue Function 0x55fd192584c0 'printf' 'int (const char *__restrict, ...)'
| `-ImplicitCastExpr 0x55fd1926ae08 <col:12> 'const char *' <ArrayToPointerDecay>
| `-StringLiteral 0x55fd1926ad70 <col:12> 'const char [27]' lvalue "DMA transfer is triggered\n"
`-CompoundStmt 0x55fd1926bfe8 <line:14:8, line:17:3>
`-CallExpr 0x55fd1926bfa8 <line:15:5, col:36> 'int'
|-ImplicitCastExpr 0x55fd1926bf90 <col:5> 'int (*)(const char *__restrict, ...)' <FunctionToPointerDecay>
| `-DeclRefExpr 0x55fd1926bf70 <col:5> 'int (const char *__restrict, ...)' lvalue Function 0x55fd192584c0 'printf' 'int (const char *__restrict, ...)'
`-ImplicitCastExpr 0x55fd1926bfd0 <col:12> 'const char *' <ArrayToPointerDecay>
`-StringLiteral 0x55fd1926bf40 <col:12> 'const char [22]' lvalue "Buffer is too small.\n"
Useful link: Exploring Clang Tooling Part 2: Examining the Clang AST with clang-query
- The sample c code
jshi19@ub2-uefi-b01:~/llvm/llvm-project/LibASTMatchersTutorial$ cat ~/llvm/wrongcode/loop-convert/simple-loops.cc
#include <stdio.h>
#define Log(str) printf(#str)
#define IO_LEN_ADDR 0x7ffe10015710;
int DMA_Read(void * buffer, int size){
//assert(addr_check(buffer, size)==TRUE);
int datalen = *(volatile int*)IO_LEN_ADDR;
printf("datalen=%d \n", datalen);
if(size >= datalen){
printf("Start reading DMA\n");
//DMAStart(buffer, datalen);
printf("DMA transfer is triggered\n");
}else{
printf("Buffer is too small.\n");
//... //exception handling
}
return 1;
}
typedef
int
(*FUN_CALL)(
void *buffer,
int size
);
int main()
{
int buffer[0x100];
FUN_CALL fun_ptr = DMA_Read;
for (int i = 0; i < 5; i++){
printf("buffer address=%p \n", buffer);
DMA_Read(buffer, 0x100);
fun_ptr (buffer, 0x500);
printf("buffer address=%x \n", fun_ptr (buffer, 0x500));
}
return 0;
}
- Match all the function callee which are referred in a function definition:
jshi19@ub2-uefi-b01:~/llvm/llvm-project/LibASTMatchersTutorial$ bin/clang-query ~/llvm/wrongcode/loop-convert/simple-loops.cc
clang-query> set bind-root false
clang-query> m callExpr(hasAncestor(functionDecl().bind("caller"))).bind("callee")
... ...
Match #7:
/home/jshi19/llvm/wrongcode/loop-convert/simple-loops.cc:36:5: note: "callee" binds here
fun_ptr (buffer, 0x500);
^~~~~~~~~~~~~~~~~~~~~~~
/home/jshi19/llvm/wrongcode/loop-convert/simple-loops.cc:29:1: note: "caller" binds here
int main()
^~~~~~~~~~
Match #8:
/home/jshi19/llvm/wrongcode/loop-convert/simple-loops.cc:37:5: note: "callee" binds here
printf("buffer address=%x \n", fun_ptr (buffer, 0x500));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/jshi19/llvm/wrongcode/loop-convert/simple-loops.cc:29:1: note: "caller" binds here
int main()
^~~~~~~~~~
Match #9:
/home/jshi19/llvm/wrongcode/loop-convert/simple-loops.cc:37:36: note: "callee" binds here
printf("buffer address=%x \n", fun_ptr (buffer, 0x500));
^~~~~~~~~~~~~~~~~~~~~~~
/home/jshi19/llvm/wrongcode/loop-convert/simple-loops.cc:29:1: note: "caller" binds here
int main()
^~~~~~~~~~
9 matches.
- Match the function which has callee:
clang-query> m functionDecl(hasDescendant(compoundStmt(has(callExpr().bind("callee"))))).bind("caller")
Match #1:
/home/jshi19/llvm/wrongcode/loop-convert/simple-loops.cc:9:3: note: "callee" binds here
printf("datalen=%d \n", datalen);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/jshi19/llvm/wrongcode/loop-convert/simple-loops.cc:6:1: note: "caller" binds here
int DMA_Read(void * buffer, int size){
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Match #2:
/home/jshi19/llvm/wrongcode/loop-convert/simple-loops.cc:34:5: note: "callee" binds here
printf("buffer address=%p \n", buffer);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/jshi19/llvm/wrongcode/loop-convert/simple-loops.cc:29:1: note: "caller" binds here
int main()
^~~~~~~~~~
2 matches.
C:\steven\LLVM\llvm-project-fork\_build_debug>cmake ..\llvm -G "Visual Studio 15 2017" -A x64 -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_BUILD_TYPE="Debug" -DLLVM_ENABLE_ASSERTIONS=ON -Thost=x64 -DLLVM_ENABLE_PROJECTS=clang;clang-tools-extra -DCMAKE_INSTALL_PREFIX=C:\steven\LLVM\llvm-project-fork\_install_debug -DLLVM_ENABLE_Z3_SOLVER=OFF -DLLVM_TARGETS_TO_BUILD="X86"
click C:\steven\LLVM\llvm-project-fork_build_debug\LLVM.sln and open the VS2017 to build the edk2-ast-parster target (Solution'LLVM'-->Clang executables-->edk2-ast-parster)
C:\steven\LLVM\llvm-project-fork\_build_debug>Debug\bin\edk2-ast-parser.exe C:\steven\LLVM\wrongcode\loop-convert\simple-loops.cc