2013-11-22 141 views
1

我想用另一个替换函数调用。例如这里是3个函数的代码 - PRINT1,print2和主:llvm替换另一个函数

#include <stdio.h> 
extern "C" { 
int print1() 
{ 
    printf("Inside print1\n"); 
    return 0xdeadbeef; 
} 
int print2() 
{ 
    printf("Inside print2\n"); 
    return 0xbeefdead; 
} 
int main(void) 
{ 
    return print1(); 
} 
}" 

我的目标是取代print2使用PRINT1的(主)。我将上面的代码编译成一个llvm :: Module *(在下面的代码中称为main),然后创建一个执行引擎。

std::string errMsg; 
llvm::ExecutionEngine *ee = 
    llvm::EngineBuilder(main).setErrorStr(&errMsg).create();  
ASSERT_NE(ee, nullptr)<<"Execution engine is nullptr:"<<errMsg; 

在这一点上,我能够从执行引擎得到所有3个功能(PRINT1,print2和主)和我能够精细执行它们。然而,当我尝试用“print2”来替换功能“PRINT1”出现问题,具体如下:

llvm::Function *print1f = main->getFunction("print1"); 
llvm::Function *print2f = main->getFunction("print2"); 
llvm::Function *mainf = main->getFunction("main"); 

//carry out the replacement 
print2f->takeName(print1f); 
ee->freeMachineCodeForFunction(mainf); 
ee->freeMachineCodeForFunction(print1f); 
print1f->replaceAllUsesWith(print2f); 
print1f->deleteBody(); 
print1f->dropAllReferences(); 
print1f->eraseFromParent(); 

//run main 
void *mainfPtr = ee->getPointerToFunction(mainf); 
mainfPtr = ee->recompileAndRelinkFunction(mainf); 
ASSERT_NE(mainfPtr, nullptr); 
ret = ((int(*)(void))(mainfPtr))(); 
*EXPECT_EQ(0xbeefdead, ret);* 

然而,RET返回为0xdeadbeef,仿佛PRINT1被调用,而不是print2。如果我按照正确的步骤更换函数调用,是否有人可以让我知道。如果有其他方法,请让我知道。

thx Vikas。

==========

+2

编译器可以在此之前做任何内联吗? (如果是这样,'main'将会有效地将'print1'的代码粘贴到它中,并且用名称替换函数将无法做到这一点...) – cHao

+1

好点cHao,但是,我是在编译模块时不会运行任何优化传递或内联。它只是使用ParseAST例程(http://clang.llvm.org/doxygen/ParseAST_8h.html)构建的,所以我猜测没有发生内联。有没有办法确保内联不会发生? – vikas

+1

cHao,你是对的。编译器的确在内联print1。谢谢你的帮助。 – vikas

回答

2

如果编译器在main内联print1,功能永远不会实际上是;相反,main将拥有其自己的专用版本print1的代码。由于它实际上不再需要引用共享的print1,因此在print2中进行交换可能不会影响main的行为。

如果您想验证这是问题(和/或防止它发生,如果是),请尝试告诉编译器不要内联。