菜鸟入门,如有任何不当之处,烦请各位路过的大佬指正,不胜感激!(顺便吐槽一句llvm的官方文档对于一些基本信息的分布真的很不合理诶!)
总述
该文件完成的主要内容就是编写一个能在基本块前插入相关计算代码的pass。所以这里只是实现将计算代码插入到相应的位置的功能,并没有实质上完成边的编号计算。只有在实际运行中,程序运行到改变的到达块时,才开始计算该边的编号。
详细剖析
首先在匿名的命名空间中,定义一个继承自ModulePass的AFLCoverage类。而对于ModulePass的理解我们可以参考官网对其的介绍:
The ModulePass class is the most general of all superclasses that you can use. Deriving from ModulePass indicates that your pass uses the entire program as a unit, referring to function bodies in no predictable order, or adding and removing functions.
因此选择继承不同类型的Pass父类就是从不同的粒度对程序进行处理。这里选择继承ModulePass就是对整个程序都进行处理。
namespace {
class AFLCoverage : public ModulePass {
然后在类外对类中的静态成员变量ID进行定义及初始化。该变量是pass标识符,即LLVM用于标识pass的。同时,在类外定义runOnModule()函数,该函数内容便是实现真正需求的部分。
char AFLCoverage::ID = 0;
bool AFLCoverage::runOnModule(Module &M) {
然后获取LLVMContext。关于LLVMContext:
This is an important class for using LLVM in a threaded context. It (opaquely) owns and manages the core “global” data of LLVM’s core infrastructure, including the type and constant uniquing tables.
LLVMContext itself provides no locking guarantees, so you should be careful to have one context per thread.
LLVMContext &C = M.getContext();
然后获取插桩率来决定插桩密度。
char* inst_ratio_str = getenv("AFL_INST_RATIO");
unsigned int inst