/* american fuzzy lop++ - LLVM CmpLog instrumentation -------------------------------------------------- Written by Andrea Fioraldi Copyright 2015, 2016 Google Inc. All rights reserved. Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: https://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include #include #include #include #include #include "llvm/Config/llvm-config.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ #include "llvm/Passes/PassPlugin.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/IR/PassManager.h" #else #include "llvm/IR/LegacyPassManager.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" #endif #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Pass.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/IRBuilder.h" #if LLVM_VERSION_MAJOR >= 4 || \ (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4) #include "llvm/IR/Verifier.h" #include "llvm/IR/DebugInfo.h" #else #include "llvm/Analysis/Verifier.h" #include "llvm/DebugInfo.h" #define nullptr 0 #endif #include #include "afl-llvm-common.h" using namespace llvm; namespace { #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ class CmpLogRoutines : public PassInfoMixin { public: CmpLogRoutines() { #else class CmpLogRoutines : public ModulePass { public: static char ID; CmpLogRoutines() : ModulePass(ID) { #endif initInstrumentList(); } #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); #else bool runOnModule(Module &M) override; #if LLVM_VERSION_MAJOR >= 4 StringRef getPassName() const override { #else const char *getPassName() const override { #endif return "cmplog routines"; } #endif private: bool hookRtns(Module &M); }; } // namespace #if LLVM_MAJOR >= 11 extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK llvmGetPassPluginInfo() { return {LLVM_PLUGIN_API_VERSION, "cmplogroutines", "v0.1", /* lambda to insert our pass into the pass pipeline. */ [](PassBuilder &PB) { #if LLVM_VERSION_MAJOR <= 13 using OptimizationLevel = typename PassBuilder::OptimizationLevel; #endif PB.registerOptimizerLastEPCallback( [](ModulePassManager &MPM, OptimizationLevel OL) { MPM.addPass(CmpLogRoutines()); }); }}; } #else char CmpLogRoutines::ID = 0; #endif bool CmpLogRoutines::hookRtns(Module &M) { std::vector calls, llvmStdStd, llvmStdC, gccStdStd, gccStdC, Memcmp, Strcmp, Strncmp; LLVMContext &C = M.getContext(); Type *VoidTy = Type::getVoidTy(C); // PointerType *VoidPtrTy = PointerType::get(VoidTy, 0); IntegerType *Int8Ty = IntegerType::getInt8Ty(C); IntegerType *Int64Ty = IntegerType::getInt64Ty(C); PointerType *i8PtrTy = PointerType::get(Int8Ty, 0); #if LLVM_VERSION_MAJOR >= 9 FunctionCallee #else Constant * #endif c = M.getOrInsertFunction("__cmplog_rtn_hook", VoidTy, i8PtrTy, i8PtrTy #if LLVM_VERSION_MAJOR < 5 , NULL #endif ); #if LLVM_VERSION_MAJOR >= 9 FunctionCallee cmplogHookFn = c; #else Function *cmplogHookFn = cast(c); #endif #if LLVM_VERSION_MAJOR >= 9 FunctionCallee #else Constant * #endif c1 = M.getOrInsertFunction("__cmplog_rtn_llvm_stdstring_stdstring", VoidTy, i8PtrTy, i8PtrTy #if LLVM_VERSION_MAJOR < 5 , NULL #endif ); #if LLVM_VERSION_MAJOR >= 9 FunctionCallee cmplogLlvmStdStd = c1; #else Function *cmplogLlvmStdStd = cast(c1); #endif #if LLVM_VERSION_MAJOR >= 9 FunctionCallee #else Constant * #endif c2 = M.getOrInsertFunction("__cmplog_rtn_llvm_stdstring_cstring", VoidTy, i8PtrTy, i8PtrTy #if LLVM_VERSION_MAJOR < 5 , NULL #endif ); #if LLVM_VERSION_MAJOR >= 9 FunctionCallee cmplogLlvmStdC = c2; #else Function *cmplogLlvmStdC = cast(c2); #endif #if LLVM_VERSION_MAJOR >= 9 FunctionCallee #else Constant * #endif c3 = M.getOrInsertFunction("__cmplog_rtn_gcc_stdstring_stdstring", VoidTy, i8PtrTy, i8PtrTy #if LLVM_VERSION_MAJOR < 5 , NULL #endif ); #if LLVM_VERSION_MAJOR >= 9 FunctionCallee cmplogGccStdStd = c3; #else Function *cmplogGccStdStd = cast(c3); #endif #if LLVM_VERSION_MAJOR >= 9 FunctionCallee #else Constant * #endif c4 = M.getOrInsertFunction("__cmplog_rtn_gcc_stdstring_cstring", VoidTy, i8PtrTy, i8PtrTy #if LLVM_VERSION_MAJOR < 5 , NULL #endif ); #if LLVM_VERSION_MAJOR >= 9 FunctionCallee cmplogGccStdC = c4; #else Function *cmplogGccStdC = cast(c4); #endif #if LLVM_VERSION_MAJOR >= 9 FunctionCallee #else Constant * #endif c5 = M.getOrInsertFunction("__cmplog_rtn_hook_n", VoidTy, i8PtrTy, i8PtrTy, Int64Ty #if LLVM_VERSION_MAJOR < 5 , NULL #endif ); #if LLVM_VERSION_MAJOR >= 9 FunctionCallee cmplogHookFnN = c5; #else Function *cmplogHookFnN = cast(c5); #endif #if LLVM_VERSION_MAJOR >= 9 FunctionCallee #else Constant * #endif c6 = M.getOrInsertFunction("__cmplog_rtn_hook_strn", VoidTy, i8PtrTy, i8PtrTy, Int64Ty #if LLVM_VERSION_MAJOR < 5 , NULL #endif ); #if LLVM_VERSION_MAJOR >= 9 FunctionCallee cmplogHookFnStrN = c6; #else Function *cmplogHookFnStrN = cast(c6); #endif #if LLVM_VERSION_MAJOR >= 9 FunctionCallee #else Constant * #endif c7 = M.getOrInsertFunction("__cmplog_rtn_hook_str", VoidTy, i8PtrTy, i8PtrTy #if LLVM_VERSION_MAJOR < 5 , NULL #endif ); #if LLVM_VERSION_MAJOR >= 9 FunctionCallee cmplogHookFnStr = c7; #else Function *cmplogHookFnStr = cast(c7); #endif GlobalVariable *AFLCmplogPtr = M.getNamedGlobal("__afl_cmp_map"); if (!AFLCmplogPtr) { AFLCmplogPtr = new GlobalVariable(M, PointerType::get(Int8Ty, 0), false, GlobalValue::ExternalWeakLinkage, 0, "__afl_cmp_map"); } Constant *Null = Constant::getNullValue(PointerType::get(Int8Ty, 0)); /* iterate over all functions, bbs and instruction and add suitable calls */ for (auto &F : M) { if (!isInInstrumentList(&F, MNAME)) continue; for (auto &BB : F) { for (auto &IN : BB) { CallInst *callInst = nullptr; if ((callInst = dyn_cast(&IN))) { Function *Callee = callInst->getCalledFunction(); if (!Callee) continue; if (callInst->getCallingConv() != llvm::CallingConv::C) continue; FunctionType *FT = Callee->getFunctionType(); std::string FuncName = Callee->getName().str(); bool isPtrRtn = FT->getNumParams() >= 2 && !FT->getReturnType()->isVoidTy() && FT->getParamType(0) == FT->getParamType(1) && FT->getParamType(0)->isPointerTy(); bool isPtrRtnN = FT->getNumParams() >= 3 && !FT->getReturnType()->isVoidTy() && FT->getParamType(0) == FT->getParamType(1) && FT->getParamType(0)->isPointerTy() && FT->getParamType(2)->isIntegerTy(); if (isPtrRtnN) { auto intTyOp = dyn_cast(callInst->getArgOperand(2)->getType()); if (intTyOp) { if (intTyOp->getBitWidth() != 32 && intTyOp->getBitWidth() != 64) { isPtrRtnN = false; } } } bool isMemcmp = (!FuncName.compare("memcmp") || !FuncName.compare("bcmp") || !FuncName.compare("CRYPTO_memcmp") || !FuncName.compare("OPENSSL_memcmp") || !FuncName.compare("memcmp_const_time") || !FuncName.compare("memcmpct")); isMemcmp &= FT->getNumParams() == 3 && FT->getReturnType()->isIntegerTy(32) && FT->getParamType(0)->isPointerTy() && FT->getParamType(1)->isPointerTy() && FT->getParamType(2)->isIntegerTy(); bool isStrcmp = (!FuncName.compare("strcmp") || !FuncName.compare("xmlStrcmp") || !FuncName.compare("xmlStrEqual") || !FuncName.compare("g_strcmp0") || !FuncName.compare("curl_strequal") || !FuncName.compare("strcsequal") || !FuncName.compare("strcasecmp") || !FuncName.compare("stricmp") || !FuncName.compare("ap_cstr_casecmp") || !FuncName.compare("OPENSSL_strcasecmp") || !FuncName.compare("xmlStrcasecmp") || !FuncName.compare("g_strcasecmp") || !FuncName.compare("g_ascii_strcasecmp") || !FuncName.compare("Curl_strcasecompare") || !FuncName.compare("Curl_safe_strcasecompare") || !FuncName.compare("cmsstrcasecmp") || !FuncName.compare("strstr") || !FuncName.compare("g_strstr_len") || !FuncName.compare("ap_strcasestr") || !FuncName.compare("xmlStrstr") || !FuncName.compare("xmlStrcasestr") || !FuncName.compare("g_str_has_prefix") || !FuncName.compare("g_str_has_suffix")); isStrcmp &= FT->getNumParams() == 2 && FT->getReturnType()->isIntegerTy(32) && FT->getParamType(0) == FT->getParamType(1) && FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext()); bool isStrncmp = (!FuncName.compare("strncmp") || !FuncName.compare("xmlStrncmp") || !FuncName.compare("curl_strnequal") || !FuncName.compare("strncasecmp") || !FuncName.compare("strnicmp") || !FuncName.compare("ap_cstr_casecmpn") || !FuncName.compare("OPENSSL_strncasecmp") || !FuncName.compare("xmlStrncasecmp") || !FuncName.compare("g_ascii_strncasecmp") || !FuncName.compare("Curl_strncasecompare") || !FuncName.compare("g_strncasecmp")); isStrncmp &= FT->getNumParams() == 3 && FT->getReturnType()->isIntegerTy(32) && FT->getParamType(0) == FT->getParamType(1) && FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext()) && FT->getParamType(2)->isIntegerTy(); bool isGccStdStringStdString = Callee->getName().find("__is_charIT_EE7__value") != std::string::npos && Callee->getName().find( "St7__cxx1112basic_stringIS2_St11char_traits") != std::string::npos && FT->getNumParams() >= 2 && FT->getParamType(0) == FT->getParamType(1) && FT->getParamType(0)->isPointerTy(); bool isGccStdStringCString = Callee->getName().find( "St7__cxx1112basic_stringIcSt11char_" "traitsIcESaIcEE7compareEPK") != std::string::npos && FT->getNumParams() >= 2 && FT->getParamType(0)->isPointerTy() && FT->getParamType(1)->isPointerTy(); bool isLlvmStdStringStdString = Callee->getName().find("_ZNSt3__1eqI") != std::string::npos && Callee->getName().find("_12basic_stringI") != std::string::npos && Callee->getName().find("_11char_traits") != std::string::npos && FT->getNumParams() >= 2 && FT->getParamType(0)->isPointerTy() && FT->getParamType(1)->isPointerTy(); bool isLlvmStdStringCString = Callee->getName().find("_ZNSt3__1eqI") != std::string::npos && Callee->getName().find("_12basic_stringI") != std::string::npos && FT->getNumParams() >= 2 && FT->getParamType(0)->isPointerTy() && FT->getParamType(1)->isPointerTy(); /* { fprintf(stderr, "F:%s C:%s argc:%u\n", F.getName().str().c_str(), Callee->getName().str().c_str(), FT->getNumParams()); fprintf(stderr, "ptr0:%u ptr1:%u ptr2:%u\n", FT->getParamType(0)->isPointerTy(), FT->getParamType(1)->isPointerTy(), FT->getNumParams() > 2 ? FT->getParamType(2)->isPointerTy() : 22 ); } */ if (isGccStdStringCString || isGccStdStringStdString || isLlvmStdStringStdString || isLlvmStdStringCString || isMemcmp || isStrcmp || isStrncmp) { isPtrRtnN = isPtrRtn = false; } if (isPtrRtnN) { isPtrRtn = false; } if (isPtrRtn) { calls.push_back(callInst); } if (isMemcmp || isPtrRtnN) { Memcmp.push_back(callInst); } if (isStrcmp) { Strcmp.push_back(callInst); } if (isStrncmp) { Strncmp.push_back(callInst); } if (isGccStdStringStdString) { gccStdStd.push_back(callInst); } if (isGccStdStringCString) { gccStdC.push_back(callInst); } if (isLlvmStdStringStdString) { llvmStdStd.push_back(callInst); } if (isLlvmStdStringCString) { llvmStdC.push_back(callInst); } } } } } if (!calls.size() && !gccStdStd.size() && !gccStdC.size() && !llvmStdStd.size() && !llvmStdC.size() && !Memcmp.size() && Strcmp.size() && Strncmp.size()) return false; /* if (!be_quiet) errs() << "Hooking " << calls.size() << " calls with pointers as arguments\n"; */ for (auto &callInst : calls) { Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); IRBuilder<> IRB2(callInst->getParent()); IRB2.SetInsertPoint(callInst); LoadInst *CmpPtr = IRB2.CreateLoad( #if LLVM_VERSION_MAJOR >= 14 PointerType::get(Int8Ty, 0), #endif AFLCmplogPtr); CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null); auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false); IRBuilder<> IRB(ThenTerm); std::vector args; Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); args.push_back(v1Pcasted); args.push_back(v2Pcasted); IRB.CreateCall(cmplogHookFn, args); // errs() << callInst->getCalledFunction()->getName() << "\n"; } for (auto &callInst : Memcmp) { Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1), *v3P = callInst->getArgOperand(2); IRBuilder<> IRB2(callInst->getParent()); IRB2.SetInsertPoint(callInst); LoadInst *CmpPtr = IRB2.CreateLoad( #if LLVM_VERSION_MAJOR >= 14 PointerType::get(Int8Ty, 0), #endif AFLCmplogPtr); CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null); auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false); IRBuilder<> IRB(ThenTerm); std::vector args; Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); Value * v3Pbitcast = IRB.CreateBitCast( v3P, IntegerType::get(C, v3P->getType()->getPrimitiveSizeInBits())); Value *v3Pcasted = IRB.CreateIntCast(v3Pbitcast, IntegerType::get(C, 64), false); args.push_back(v1Pcasted); args.push_back(v2Pcasted); args.push_back(v3Pcasted); IRB.CreateCall(cmplogHookFnN, args); // errs() << callInst->getCalledFunction()->getName() << "\n"; } for (auto &callInst : Strcmp) { Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); IRBuilder<> IRB2(callInst->getParent()); IRB2.SetInsertPoint(callInst); LoadInst *CmpPtr = IRB2.CreateLoad( #if LLVM_VERSION_MAJOR >= 14 PointerType::get(Int8Ty, 0), #endif AFLCmplogPtr); CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null); auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false); IRBuilder<> IRB(ThenTerm); std::vector args; Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); args.push_back(v1Pcasted); args.push_back(v2Pcasted); IRB.CreateCall(cmplogHookFnStr, args); // errs() << callInst->getCalledFunction()->getName() << "\n"; } for (auto &callInst : Strncmp) { Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1), *v3P = callInst->getArgOperand(2); IRBuilder<> IRB2(callInst->getParent()); IRB2.SetInsertPoint(callInst); LoadInst *CmpPtr = IRB2.CreateLoad( #if LLVM_VERSION_MAJOR >= 14 PointerType::get(Int8Ty, 0), #endif AFLCmplogPtr); CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null); auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false); IRBuilder<> IRB(ThenTerm); std::vector args; Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); Value * v3Pbitcast = IRB.CreateBitCast( v3P, IntegerType::get(C, v3P->getType()->getPrimitiveSizeInBits())); Value *v3Pcasted = IRB.CreateIntCast(v3Pbitcast, IntegerType::get(C, 64), false); args.push_back(v1Pcasted); args.push_back(v2Pcasted); args.push_back(v3Pcasted); IRB.CreateCall(cmplogHookFnStrN, args); // errs() << callInst->getCalledFunction()->getName() << "\n"; } for (auto &callInst : gccStdStd) { Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); IRBuilder<> IRB2(callInst->getParent()); IRB2.SetInsertPoint(callInst); LoadInst *CmpPtr = IRB2.CreateLoad( #if LLVM_VERSION_MAJOR >= 14 PointerType::get(Int8Ty, 0), #endif AFLCmplogPtr); CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null); auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false); IRBuilder<> IRB(ThenTerm); std::vector args; Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); args.push_back(v1Pcasted); args.push_back(v2Pcasted); IRB.CreateCall(cmplogGccStdStd, args); // errs() << callInst->getCalledFunction()->getName() << "\n"; } for (auto &callInst : gccStdC) { Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); IRBuilder<> IRB2(callInst->getParent()); IRB2.SetInsertPoint(callInst); LoadInst *CmpPtr = IRB2.CreateLoad( #if LLVM_VERSION_MAJOR >= 14 PointerType::get(Int8Ty, 0), #endif AFLCmplogPtr); CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null); auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false); IRBuilder<> IRB(ThenTerm); std::vector args; Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); args.push_back(v1Pcasted); args.push_back(v2Pcasted); IRB.CreateCall(cmplogGccStdC, args); // errs() << callInst->getCalledFunction()->getName() << "\n"; } for (auto &callInst : llvmStdStd) { Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); IRBuilder<> IRB2(callInst->getParent()); IRB2.SetInsertPoint(callInst); LoadInst *CmpPtr = IRB2.CreateLoad( #if LLVM_VERSION_MAJOR >= 14 PointerType::get(Int8Ty, 0), #endif AFLCmplogPtr); CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null); auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false); IRBuilder<> IRB(ThenTerm); std::vector args; Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); args.push_back(v1Pcasted); args.push_back(v2Pcasted); IRB.CreateCall(cmplogLlvmStdStd, args); // errs() << callInst->getCalledFunction()->getName() << "\n"; } for (auto &callInst : llvmStdC) { Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); IRBuilder<> IRB2(callInst->getParent()); IRB2.SetInsertPoint(callInst); LoadInst *CmpPtr = IRB2.CreateLoad( #if LLVM_VERSION_MAJOR >= 14 PointerType::get(Int8Ty, 0), #endif AFLCmplogPtr); CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null); auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false); IRBuilder<> IRB(ThenTerm); std::vector args; Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); args.push_back(v1Pcasted); args.push_back(v2Pcasted); IRB.CreateCall(cmplogLlvmStdC, args); // errs() << callInst->getCalledFunction()->getName() << "\n"; } return true; } #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ PreservedAnalyses CmpLogRoutines::run(Module &M, ModuleAnalysisManager &MAM) { #else bool CmpLogRoutines::runOnModule(Module &M) { #endif if (getenv("AFL_QUIET") == NULL) printf("Running cmplog-routines-pass by andreafioraldi@gmail.com\n"); else be_quiet = 1; hookRtns(M); #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ auto PA = PreservedAnalyses::all(); #endif verifyModule(M); #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ return PA; #else return true; #endif } #if LLVM_VERSION_MAJOR < 11 /* use old pass manager */ static void registerCmpLogRoutinesPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { auto p = new CmpLogRoutines(); PM.add(p); } static RegisterStandardPasses RegisterCmpLogRoutinesPass( PassManagerBuilder::EP_OptimizerLast, registerCmpLogRoutinesPass); static RegisterStandardPasses RegisterCmpLogRoutinesPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogRoutinesPass); #if LLVM_VERSION_MAJOR >= 11 static RegisterStandardPasses RegisterCmpLogRoutinesPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCmpLogRoutinesPass); #endif #endif