问题
在做一个project的时候需要使用llvm的pass对函数进行插桩,在每一个函数头之前插入一条指令rdrand %rax,在寻找llvm基本指令之后发现并没有生成随机数的指令,这时就想到了llvm中intrinsic函数中是否有关于rdrand指令的函数,在对llvm整个源码进行扫描之后,发现有x86的rdrand的intrinsic函数:
1 |
|
既然有对它们的定义,那是否有关于它们的使用呢,又经过一番查找,终于在一个测试文件中(/test/CodeGen/X86/rdrand.ll)找到相应的使用:
1 | declare {i16, i32} @llvm.x86.rdrand.16() |
这个系列函数是对rdrandx_step(address)系列函数的包装,在这些函数中是生成随机数,并将该随机数保存到address参数中。发现在该系列函数中对@llvm.x86.rdrand.xx()系列函数的调用,可以发现,在该函数第一个语句是对@llvm.x86.rdrand.xx() intrinsic函数的调用,该函数返回一个StructType类型的结果,该结果一共有两个成员组成,第一个成员是@llvm.x86.rdrand.xx()函数产生的随机数,第二个参数表示该函数是否调用成功。第二个语句就是从结果中取出随机数。弄清了该函数的逻辑后就可以通过llvm C API产生相应的IR指令。
llvm C API
下面是我通过llvm的C API产生的相应的IR指令的代码:
1 |
|
注意事项
在生成了.ll文件后,需要用llc工具生成二进制文件,此时需要添加-mattr=rdrnd的属性:
1 | llc -filetype=obj input.ll -mattr=+rdrnd -o output.o |
否则会出现LLVM ERROR: Cannot select: t74: i64,i32,ch = X86ISD::RDRAND t0错误