gpt4 book ai didi

clang - 使用 ASTMatcher 获取所有 "malloc"调用

转载 作者:行者123 更新时间:2023-12-04 02:20:04 28 4
gpt4 key购买 nike

我正在尝试获取所有 malloc使用 ASTMatcher 调用在 clang 中。这是代码示例:

Finder.addMatcher(
callExpr(
hasParent(binaryOperator(
hasOperatorName("=")).bind("assignment")),
declRefExpr(to(functionDecl(hasName("malloc"))))).bind("functionCall"),
&HandlerForFunctionCall);

它编译得很好。但我仍然无法得到任何 malloc来电。我怎样才能得到所有 malloc使用 clang ASTmatcher 调用?

最佳答案

问题
malloc 的签名函数定义如下:

void* malloc (size_t size);

为了分配 malloc的返回值指向除 void* 之外的任何类型的指针,你必须投它。
虽然 C++ 要求您进行显式转换,但 C 编译器会为您隐式执行此操作。所以即使你写

int *a = malloc(sizeof(*a));

编译器将隐式转换 RHS 表达式。那将相当于

int *a = (int*) malloc(sizeof(*a));

您正在使用 hasParent缩小匹配器, 只匹配直接 parent 而不匹配任何祖先 .
因此,您的匹配器只会匹配没有任何类型转换的分配。

您的 declRefExpr 也发生了几乎相同的事情。 .
C 标准说函数会自动衰减为指向函数的指针。
Clang 隐式转换 mallocvoid *(*)(size_t)这会破坏您的匹配器层次结构。

可能的解决方案

嗯,这取决于你真正想要做什么。
首先,您通常可以使用以下代码段修复选择 malloc 函数的部分:

callExpr(callee(functionDecl(hasName("malloc"))))

其余的取决于您要选择的内容。
如果您只对匹配上面第一个示例中的直接分配感兴趣,那么您可以使用 ignoringImpCasts匹配器。
由于某种原因,我无法在您编写时将其插入匹配器中,因此只需反转匹配器即可。
看起来像这样:

binaryOperator(
hasOperatorName("="),
hasRHS(ignoringImpCasts(
callExpr(
callee(functionDecl(hasName("malloc")))
).bind("functionCall")
))
).bind("assignment")

如果您还想包含第二个示例中的显式转换,请使用 ignoringParenImpCasts反而:

binaryOperator(
hasOperatorName("="),
hasRHS(ignoringParenImpCasts(
callExpr(
callee(functionDecl(hasName("malloc")))
).bind("functionCall")
))
).bind("assignment")

如果您对包含 malloc 的任意表达式的所有赋值感兴趣, 使用 hasAncestor反而。它不仅匹配直接父节点,还会向上遍历直到匹配您的节点:

callExpr(
callee(functionDecl(hasName("malloc"))),
hasAncestor(
binaryOperator(hasOperatorName("=")).bind("assignment")
)
).bind("functionCall")

还有一件事。
您可能只对直接匹配源代码中定义的内容而不是包含的头文件感兴趣。
只需添加 unless(isExpansionInSystemHeader())到您的顶级匹配器,它将排除系统 header 中的所有定义。

请注意,此代码已使用 LLVM 3.7 进行了测试, future 的更改可能会破坏它。

如何调试

好吧,那么我们到底应该怎么知道这一切呢?
事实证明,Clang 已经为您提供了您所需要的一切 :)
具体来说,您可能会对两个功能感兴趣。

当您使用 -Xclang ast-dump -fsyntax-only 调用 Clang 时它将打印出翻译单元的漂亮多彩的 AST。发现包含来自系统 header 的所有声明的巨大序言不要感到惊讶,因为它必须首先运行预处理器才能生成 AST。例子:

$ clang -Xclang -ast-dump -fsyntax-only example.c
...

`-FunctionDecl 0x3f2fc28 <line:19:1, line:31:1> line:19:5 main 'int ()'
`-CompoundStmt 0x3f307b8 <line:20:1, line:31:1>
|-BinaryOperator 0x3f2ff38 <line:22:3, col:29> 'int *' '='
| |-DeclRefExpr 0x3f2fd40 <col:3> 'int *' lvalue Var 0x3f2f388 'a' 'int *'
| `-ImplicitCastExpr 0x3f2ff20 <col:7, col:29> 'int *' <BitCast>
| `-CallExpr 0x3f2fef0 <col:7, col:29> 'void *'
| |-ImplicitCastExpr 0x3f2fed8 <col:7> 'void *(*)(unsigned long)' <FunctionToPointerDecay>
| | `-DeclRefExpr 0x3f2fd68 <col:7> 'void *(unsigned long)' Function 0x3f1cdd0 'malloc' 'void *(unsigned long)'
| `-BinaryOperator 0x3f2fe88 <col:15, col:28> 'unsigned long' '*'
| |-ImplicitCastExpr 0x3f2fe70 <col:15> 'unsigned long' <IntegralCast>
| | `-ImplicitCastExpr 0x3f2fe58 <col:15> 'int' <LValueToRValue>
| | `-DeclRefExpr 0x3f2fd90 <col:15> 'int' lvalue Var 0x3f2f488 'n' 'int'
| `-UnaryExprOrTypeTraitExpr 0x3f2fe38 <col:19, col:28> 'unsigned long' sizeof
| `-ParenExpr 0x3f2fe18 <col:25, col:28> 'int' lvalue
| `-UnaryOperator 0x3f2fdf8 <col:26, col:27> 'int' lvalue prefix '*'
| `-ImplicitCastExpr 0x3f2fde0 <col:27> 'int *' <LValueToRValue>
| `-DeclRefExpr 0x3f2fdb8 <col:27> 'int *' lvalue Var 0x3f2f388 'a' 'int *'

...

如果您从源代码编译它,那么还有与 clang 一起构建的 clang-query。
它是 libTooling 的一个很好的例子,同时也是对开发的绝对惊人的帮助。
您只需在示例源文件上运行它并使用它来测试您的匹配器(请注意,它隐式地将“root”绑定(bind)到完整的匹配器):

$ <llvm>/bin/clang-query example.c --
clang-query> match callExpr(callee(functionDecl(hasName("malloc"))),hasAncestor(binaryOperator(hasOperatorName("=")).bind("assignment"))).bind("functionCall")

Match #1:

/vagrant/tests/true-valid-memsafety.c:22:3: note: "assignment" binds here
a = malloc (n * sizeof(*a));
^~~~~~~~~~~~~~~~~~~~~~~~~~~
/vagrant/tests/true-valid-memsafety.c:22:7: note: "functionCall" binds here
a = malloc (n * sizeof(*a));
^~~~~~~~~~~~~~~~~~~~~~~
/vagrant/tests/true-valid-memsafety.c:22:7: note: "root" binds here
a = malloc (n * sizeof(*a));
^~~~~~~~~~~~~~~~~~~~~~~

Match #2:

/vagrant/tests/true-valid-memsafety.c:23:3: note: "assignment" binds here
b = malloc (n * sizeof(*b));
^~~~~~~~~~~~~~~~~~~~~~~~~~~
/vagrant/tests/true-valid-memsafety.c:23:7: note: "functionCall" binds here
b = malloc (n * sizeof(*b));
^~~~~~~~~~~~~~~~~~~~~~~
/vagrant/tests/true-valid-memsafety.c:23:7: note: "root" binds here
b = malloc (n * sizeof(*b));
^~~~~~~~~~~~~~~~~~~~~~~
2 matches.

如果您对该主题的更多信息感兴趣,请前往 this excellent blog post Eli Bendersky 提供了一个很好的概述和介绍。可以找到 AST 匹配器的完整文档 here .

关于clang - 使用 ASTMatcher 获取所有 "malloc"调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29380948/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com