Clang插件:编译期间修改AST

6
我正在开发一个clang插件,用于将日志字符串外部化(以减小嵌入式项目的二进制文件大小),需要修改AST(因此在预处理器之后,在编译之前进行)。
目前,我能够成功匹配要替换的节点(使用RecursiveASTVisitor<T>),并正确提取构建替换所需的数据。
在我的访问者的VisitStmt方法中,我正在遍历子节点,当找到匹配项时,尝试通过迭代器将匹配的表达式节点(CallExpr,返回int)替换为新节点(IntegerLiteral): *it = clang::IntegerLiteral::Create(context, { 32, value, false }, context.IntTy, old->getLocStart()). 然而,当我尝试使用我的插件编译示例程序时,clang返回成功状态代码,但没有生成目标文件。
$ clang -std=c11 -Xclang -load -Xclang /tmp/plugin.so -Xclang -plugin -Xclang string-externalise -Xclang -plugin-arg-string-externalise -Xclang -lut-file=lut.txt -c -o example.o example.c

$ echo $?
0

$ stat example.o
stat: cannot stat 'example.o': No such file or directory

如果我尝试转储AST以验证我是否正确修改了它,则clang也不会输出任何内容。但是如果我禁用我的插件(删除与之相关的clang所有参数),则可以转储(原始未修改的)AST。
我试图进行的具体AST修改是将对占位符函数(返回int)的调用替换为整数字面量(由插件确定的值)。
例如,将此CallExpr子树替换为IntegerLiteral:
| |-CallExpr 0x556d460b3ab8 <line:7:42, col:78> 'int'
| | |-ImplicitCastExpr 0x556d460b3aa0 <col:42> 'int (*)(const char *, int)' <FunctionToPointerDecay>
| | | `-DeclRefExpr 0x556d460b3a20 <col:42> 'int (const char *, int)' Function 0x556d460b22d8 '__externalise_location' 'int (const char *, int)'
| | |-ImplicitCastExpr 0x556d460b3b08 <<scratch space>:26:1> 'const char *' <BitCast>
| | | `-ImplicitCastExpr 0x556d460b3af0 <col:1> 'char *' <ArrayToPointerDecay>
| | |   `-StringLiteral 0x556d460b3a48 <col:1> 'char [10]' lvalue "example.c"
| | `-IntegerLiteral 0x556d460b3a80 <line:27:1> 'int' 22

或者将这个CallExpr子树替换为一个IntegerLiteral

| |-CallExpr 0x556d460b3b98 <example.c:6:26, col:46> 'int'
| | |-ImplicitCastExpr 0x556d460b3b80 <col:26> 'int (*)(const char *)' <FunctionToPointerDecay>
| | | `-DeclRefExpr 0x556d460b3b20 <col:26> 'int (const char *)' Function 0x556d460b20c0 '__externalise' 'int (const char *)'
| | `-ImplicitCastExpr 0x556d460b3be0 <line:22:6> 'const char *' <BitCast>
| |   `-ImplicitCastExpr 0x556d460b3bc8 <col:6> 'char *' <ArrayToPointerDecay>
| |     `-StringLiteral 0x556d460b3b48 <col:6> 'char [10]' lvalue "hello %s\n"

第一个问题已解决:https://dev59.com/kqHia4cB1Zd3GeqPREhB#46695100。现在要修复段错误,并查看我的AST修改是否有效。如果成功,将发布完整的解决方案。 - Mark K Cowan
你找到解决方案了吗? - horro
1
你需要使用-add-plugin而不是-plugin。 - Swetko
@MarkKCowan 即将开始类似的尝试。你找到解决方案了吗? - Sozin's Comet
@Sozin'sComet 我确实尝试过,但不幸的是我很快就离开了公司,忘记了确切的解决方案。@user1068799 的建议使用 -add-plugin-plugin 似乎非常熟悉。 - Mark K Cowan
显示剩余2条评论
1个回答

0

虽然已经过去了几年,我不再拥有原始代码库的访问权限,但最近我为别人研究了这个问题。

根据我能记起来的内容,加上Clang文档另一个我几年前点赞的SO答案,解决方案基本上是:

  • 使用-add-plugin而不是-plugin(2018年的原始解决方案),或者
  • 按照链接的Clang文档中所述公开getActionType

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接