Him*_*har 11 c c++ instrumentation static-analysis
我想写一个LLVM传递来检测每个内存访问.这是我想要做的.
给定任何C/C++程序(如下面给出的那样),我试图在每个读/写内存的指令之前和之后插入一些函数的调用.例如,考虑下面的C++程序(Account.cpp)
#include <stdio.h>
class Account {
int balance;
public:
Account(int b)
{
balance = b;
}
~Account(){ }
int read()
{
int r;
r = balance;
return r;
}
void deposit(int n)
{
balance = balance + n;
}
void withdraw(int n)
{
int r = read();
balance = r - n;
}
};
int main ()
{
Account* a = new Account(10);
a->deposit(1);
a->withdraw(2);
delete a;
}
Run Code Online (Sandbox Code Playgroud)
所以在仪器之后我的程序应该是这样的:
#include <stdio.h>
class Account
{
int balance;
public:
Account(int b)
{
balance = b;
}
~Account(){ }
int read()
{
int r;
foo();
r = balance;
foo();
return r;
}
void deposit(int n)
{
foo();
balance = balance + n;
foo();
}
void withdraw(int n)
{
foo();
int r = read();
foo();
foo();
balance = r - n;
foo();
}
};
int main ()
{
Account* a = new Account(10);
a->deposit(1);
a->withdraw(2);
delete a;
}
Run Code Online (Sandbox Code Playgroud)
其中foo()可以是任何函数,比如获取当前系统时间或递增计数器......等等.
请给我举例(源代码,教程等)以及如何运行它的步骤.我已经阅读了关于如何在http://llvm.org/docs/WritingAnLLVMPass.html上提供LLVM Pass的教程,但是无法弄清楚如何为上述问题写一个传递.
我对LLVM不太熟悉,但我对GCC(及其插件机制)更熟悉,因为我是GCC MELT的主要作者(扩展GCC的高级域特定语言,顺便说一下你可以用于你的问题).所以我会试着回答一般问题.
您应该首先知道为什么要调整编译器(或静态分析器).这是一个有价值的目标,但它确实有缺点(特别是,在您的C++程序中重新定义了一些运算符或其他构造).
扩展编译器(无论是GCC还是LLVM或其他东西)的要点是你很可能应该处理它的所有内部表示(你可能不能跳过它的一部分,除非你有一个非常狭窄的定义问题).对于GCC来说,它意味着处理100多种Tree-s和近20种Gimple-s:在GCC中端,tree-s代表操作数和声明,gimple -s代表指令.这种方法的优点是,一旦完成,您的扩展应该能够处理编译器可接受的任何软件.缺点是编译器的内部表示的复杂性(这可以通过编译器接受的C&C++源语言的定义的复杂性,以及它们产生的目标机器代码的复杂性以及随着距离的增加来解释.源语言和目标语言之间).
因此,攻击一般编译器(无论是GCC还是LLVM),还是静态分析器(如Frama-C),是一项相当大的任务(超过一个月的工作,而不是几天).要只处理像你所展示的微小的C++程序,它是不值得的.但是,如果您明确处理大型源代码软件库,那绝对值得努力.
问候
尝试这样的事情:(尽管事实上正在插入项目,但您需要填充空白并使迭代器循环工作)
class ThePass : public llvm::BasicBlockPass {
public:
ThePass() : BasicBlockPass() {}
virtual bool runOnBasicBlock(llvm::BasicBlock &bb);
};
bool ThePass::runOnBasicBlock(BasicBlock &bb) {
bool retval = false;
for (BasicBlock::iterator bbit = bb.begin(), bbie = bb.end(); bbit != bbie;
++bbit) { // Make loop work given updates
Instruction *i = bbit;
CallInst * beforeCall = // INSERT THIS
beforeCall->insertBefore(i);
if (!i->isTerminator()) {
CallInst * afterCall = // INSERT THIS
afterCall->insertAfter(i);
}
}
return retval;
}
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助!