检查函数参数是否是LLVM中的全局变量



这个问题与几年前发布的问题类似(跟踪llvm中使用的全局变量(,但没有得到回答(我也无法实现该帖子中的建议(。我想详细说明这个问题,并发布我的解决方案,看看我是否能得到一些见解。

假设我有一个简短的测试代码,如下所示:

char a[10];
void foo(char *buf, int test) {
printf("Foo %pn", buf);
buf[1] = '1';
}
int main() {
foo(a, 17);
}

这被翻译成LLVM IR,如下所示(为了简洁起见,进行了删减(:

@test_global = dso_local global i32 17, align 4
@a = dso_local global [10 x i8] zeroinitializer, align 1
define dso_local void @foo(i8* %0, i32 %1) #0 {
%3 = alloca i8*, align 8
...
store i8* %0, i8** %3, align 8
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
...
store i32 0, i32* %1, align 4
call void @foo(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @a, i64 0, i64 0), i32 17)

因此,问题本身一开始很容易解决。我只需要检查函数@foo中的指令store i8* %0, i8** %3, align 8,即%0指向全局内存?因为%0call函数call void @foo(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @a, i64 0, i64 0), i32 17)中的第一个参数,所以我认为这是最简单的方法

然而,我只是有点不知所措,我需要做些什么来实现这样的检查。我一直在研究解决这个问题,但我能做的最好的事情就是有一个LLVM通行证,看起来像这样:

void checkGlobal(Function &F, AAResults &AA) {
SetVector<Value *> Ptrs; // worklist of pointers
for (auto &arg : F.args()) {
if (arg.getType()->isPointerTy()){
Ptrs.insert(&arg);
}
}
for (auto item : Ptrs) {
for (auto user : item->users()) {
if (auto storeI = dyn_cast<StoreInst>(user)) {
errs() << *storeI->getOperand(0) << " " << *storeI->getPointerOperand() << "n";
// this will find the store i8* %0, i8** %3, align 8 
// LLVM IR instruction with respective operands
}
}     
}
}

如果我需要对@foo函数中的指针i8* %0使用别名分析,我会将别名分析结果AAResults传递到此函数中(如果可能,请告诉我(。

我觉得我至少朝着解决这个问题的正确方向前进,但目前停滞不前;我还尝试从LLVM模块级别解决这个问题,方法是获取全局变量结果,比如这样:

auto &list = M.getGlobalList();
for (auto &gv : list) {
for (auto use : gv.users()) {
errs() << *use << "n"; 
}
}

上面的代码将为@foo函数返回类似的内容:i8* getelementptr inbounds ([10 x i8], [10 x i8]* @a, i64 0, i64 0),看看我是否可以使用这些信息来分配传入了全局变量作为参数的函数,并手动解决问题。然而,这种方法是不可靠的,而且非常薄弱。

谢谢你的任何建议,如果我的问题有什么不清楚的地方,请告诉我。

从某种意义上说,函数的目的是将代码划分为执行某些操作的部分和提供数据进行操作的部分。这意味着函数内部的代码不知道所提供的是否是全局变量,是设计的

当代码按设计工作时,可能会很烦人;(你有几个可能的解决办法。

首先,如果不能从模块之外调用函数,则可以将函数的每个参数连接到调用该函数的CallInst/InInvokeInst指令的操作数,并查看这些操作数是否为全局变量。这可能是一个递归过程,您必须考虑如果一些调用方提供全局变量,而其他调用方不提供,或者如果信息不完整,因为您不一定能决定特定的调用指令是否调用您的函数,会发生什么。

另一种是在运行时查看它。通常,每个平台都会将全局变量定位在地址空间的特定部分,你可以找到它是什么。如果你有一个指针,你可以将其强制转换为int,并将其与链接器放置全局变量的地址空间的开始和结束进行比较。

相关内容

  • 没有找到相关文章

最新更新