diff --git a/libafl/src/mutators/token_mutations.rs b/libafl/src/mutators/token_mutations.rs index 8055ee4556..f2b487afba 100644 --- a/libafl/src/mutators/token_mutations.rs +++ b/libafl/src/mutators/token_mutations.rs @@ -715,8 +715,8 @@ impl AFLppRedQueen { }; // Try arith - let diff: i64 = (pattern - b_val) as i64; - let new_diff: i64 = (another_pattern - o_b_val) as i64; + let diff = pattern as i64 - b_val as i64; + let new_diff = another_pattern as i64 - o_b_val as i64; if diff == new_diff && diff != 0 { let new_repl: u64 = (repl as i64 - diff) as u64; diff --git a/libafl_cc/build.rs b/libafl_cc/build.rs index ce75ebf795..167af6b0a6 100644 --- a/libafl_cc/build.rs +++ b/libafl_cc/build.rs @@ -408,7 +408,6 @@ pub const LIBAFL_CC_LLVM_VERSION: Option = None; "autotokens-pass.cc", "coverage-accounting-pass.cc", "cmplog-instructions-pass.cc", - "cmplog-switches-pass.cc", ] { build_pass( bindir_path, diff --git a/libafl_cc/src/clang.rs b/libafl_cc/src/clang.rs index cbb9c2731d..2b0fe36a69 100644 --- a/libafl_cc/src/clang.rs +++ b/libafl_cc/src/clang.rs @@ -44,9 +44,6 @@ pub enum LLVMPasses { #[cfg(unix)] /// The CmpLog Instruction pass CmpLogInstructions, - #[cfg(unix)] - /// The CmpLog Switch pass - CmpLogSwitches, } impl LLVMPasses { @@ -69,9 +66,6 @@ impl LLVMPasses { #[cfg(unix)] LLVMPasses::CmpLogInstructions => PathBuf::from(env!("OUT_DIR")) .join(format!("cmplog-instructions-pass.{}", dll_extension())), - #[cfg(unix)] - LLVMPasses::CmpLogSwitches => PathBuf::from(env!("OUT_DIR")) - .join(format!("cmplog-switches-pass.{}", dll_extension())), } } } diff --git a/libafl_cc/src/cmplog-instructions-pass.cc b/libafl_cc/src/cmplog-instructions-pass.cc index fb44c57a8e..41eb3b0c26 100644 --- a/libafl_cc/src/cmplog-instructions-pass.cc +++ b/libafl_cc/src/cmplog-instructions-pass.cc @@ -98,7 +98,11 @@ llvmGetPassPluginInfo() { #if LLVM_VERSION_MAJOR <= 13 using OptimizationLevel = typename PassBuilder::OptimizationLevel; #endif + #if LLVM_VERSION_MAJOR >= 16 + PB.registerOptimizerEarlyEPCallback( + #else PB.registerOptimizerLastEPCallback( + #endif [](ModulePassManager &MPM, OptimizationLevel OL) { MPM.addPass(CmpLogInstructions()); }); @@ -121,6 +125,7 @@ Iterator Unique(Iterator first, Iterator last) { bool CmpLogInstructions::hookInstrs(Module &M) { std::vector icomps; + std::vector switches; LLVMContext &C = M.getContext(); Type *VoidTy = Type::getVoidTy(C); @@ -202,8 +207,16 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } } } + + for (auto &BB : F) { + SwitchInst *switchInst = nullptr; + if ((switchInst = dyn_cast(BB.getTerminator()))) { + if (switchInst->getNumCases() > 1) { switches.push_back(switchInst); } + } + } } + switches.erase(Unique(switches.begin(), switches.end()), switches.end()); if (icomps.size()) { // if (!be_quiet) errs() << "Hooking " << icomps.size() << // " cmp instructions\n"; @@ -500,11 +513,114 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } } - if (icomps.size()) { - return true; - } else { - return false; + if (switches.size()) { + for (auto &SI : switches) { + Value *Val = SI->getCondition(); + unsigned int max_size = Val->getType()->getIntegerBitWidth(); + unsigned int cast_size; + unsigned char do_cast = 0; + + if (!SI->getNumCases() || max_size < 16) { + // skipping trivial switch + continue; + } + + if (max_size % 8) { + max_size = (((max_size / 8) + 1) * 8); + do_cast = 1; + } + + if (max_size > 128) { + // can't handle this + + max_size = 128; + do_cast = 1; + } + + IRBuilder<> IRB(SI->getParent()); + IRB.SetInsertPoint(SI); + + switch (max_size) { + case 8: + case 16: + case 32: + case 64: + case 128: + cast_size = max_size; + break; + default: + cast_size = 128; + do_cast = 1; + } + + // The predicate of the switch clause + Value *CompareTo = Val; + if (do_cast) { + CompareTo = + IRB.CreateIntCast(CompareTo, IntegerType::get(C, cast_size), false); + } + + for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e; + ++i) { + // Who uses LLVM Major < 5?? :p + ConstantInt *cint = i->getCaseValue(); + + if (cint) { + std::vector args; + args.push_back(CompareTo); + + Value *new_param = cint; + if (do_cast) { + new_param = + IRB.CreateIntCast(cint, IntegerType::get(C, cast_size), false); + } + + if (new_param) { + args.push_back(new_param); + if (CmplogExtended) { + ConstantInt *attribute = ConstantInt::get(Int8Ty, 1); + args.push_back(attribute); + } + if (cast_size != max_size) { + // not 8, 16, 32, 64, 128. + ConstantInt *bitsize = + ConstantInt::get(Int8Ty, (max_size / 8) - 1); + args.push_back(bitsize); // we have the arg for size in hookinsN + } + + switch (cast_size) { + case 8: + IRB.CreateCall(cmplogHookIns1, args); + break; + case 16: + IRB.CreateCall(cmplogHookIns2, args); + break; + case 32: + IRB.CreateCall(cmplogHookIns4, args); + break; + case 64: + IRB.CreateCall(cmplogHookIns8, args); + break; + case 128: +#ifdef WORD_SIZE_64 + if (max_size == 128) { + IRB.CreateCall(cmplogHookIns16, args); + + } else { + IRB.CreateCall(cmplogHookInsN, args); + } + +#endif + break; + default: + break; + } + } + } + } + } } + return true; } #if USE_NEW_PM diff --git a/libafl_cc/src/cmplog-routines-pass.cc b/libafl_cc/src/cmplog-routines-pass.cc index 073dc9bc5e..0a3fdf35bc 100644 --- a/libafl_cc/src/cmplog-routines-pass.cc +++ b/libafl_cc/src/cmplog-routines-pass.cc @@ -50,7 +50,9 @@ #include using namespace llvm; - +static cl::opt CmplogExtended("cmplog_routines_extended", + cl::desc("Uses extended header"), + cl::init(false), cl::NotHidden); namespace { #if USE_NEW_PM @@ -114,150 +116,85 @@ bool CmpLogRoutines::hookRtns(Module &M) { // PointerType *VoidPtrTy = PointerType::get(VoidTy, 0); IntegerType *Int8Ty = IntegerType::getInt8Ty(C); IntegerType *Int64Ty = IntegerType::getInt64Ty(C); + IntegerType *Int32Ty = IntegerType::getInt32Ty(C); PointerType *i8PtrTy = PointerType::get(Int8Ty, 0); -#if LLVM_VERSION_MAJOR < 9 - Constant * -#else - FunctionCallee -#endif - c = M.getOrInsertFunction("__cmplog_rtn_hook", VoidTy, i8PtrTy, i8PtrTy -#if LLVM_VERSION_MAJOR < 5 - , - NULL -#endif - ); -#if LLVM_VERSION_MAJOR < 9 - Function *cmplogHookFn = cast(c); -#else - FunctionCallee cmplogHookFn = c; -#endif + FunctionCallee cmplogHookFn; + FunctionCallee cmplogLlvmStdStd; + FunctionCallee cmplogLlvmStdC; + FunctionCallee cmplogGccStdStd; + FunctionCallee cmplogGccStdC; + FunctionCallee cmplogHookFnN; + FunctionCallee cmplogHookFnStrN; + FunctionCallee cmplogHookFnStr; + + if (CmplogExtended) { + cmplogHookFn = M.getOrInsertFunction("__cmplog_rtn_hook_extended", VoidTy, + i8PtrTy, i8PtrTy); + } else { + cmplogHookFn = + M.getOrInsertFunction("__cmplog_rtn_hook", VoidTy, i8PtrTy, i8PtrTy); + } -#if LLVM_VERSION_MAJOR < 9 - Constant * -#else - FunctionCallee -#endif - c1 = M.getOrInsertFunction("__cmplog_rtn_llvm_stdstring_stdstring", - VoidTy, i8PtrTy, i8PtrTy -#if LLVM_VERSION_MAJOR < 5 - , - NULL -#endif - ); -#if LLVM_VERSION_MAJOR < 9 - Function *cmplogLlvmStdStd = cast(c1); -#else - FunctionCallee cmplogLlvmStdStd = c1; -#endif + if (CmplogExtended) { + cmplogLlvmStdStd = + M.getOrInsertFunction("__cmplog_rtn_llvm_stdstring_stdstring_extended", + VoidTy, i8PtrTy, i8PtrTy); + } else { + cmplogLlvmStdStd = M.getOrInsertFunction( + "__cmplog_rtn_llvm_stdstring_stdstring", VoidTy, i8PtrTy, i8PtrTy); + } -#if LLVM_VERSION_MAJOR < 9 - Constant * -#else - FunctionCallee -#endif - c2 = M.getOrInsertFunction("__cmplog_rtn_llvm_stdstring_cstring", VoidTy, - i8PtrTy, i8PtrTy -#if LLVM_VERSION_MAJOR < 5 - , - NULL -#endif - ); -#if LLVM_VERSION_MAJOR < 9 - Function *cmplogLlvmStdC = cast(c2); -#else - FunctionCallee cmplogLlvmStdC = c2; -#endif + if (CmplogExtended) { + cmplogLlvmStdC = + M.getOrInsertFunction("__cmplog_rtn_llvm_stdstring_cstring_extended", + VoidTy, i8PtrTy, i8PtrTy); + } else { + cmplogLlvmStdC = M.getOrInsertFunction( + "__cmplog_rtn_llvm_stdstring_cstring", VoidTy, i8PtrTy, i8PtrTy); + } -#if LLVM_VERSION_MAJOR < 9 - Constant * -#else - FunctionCallee -#endif - c3 = M.getOrInsertFunction("__cmplog_rtn_gcc_stdstring_stdstring", VoidTy, - i8PtrTy, i8PtrTy -#if LLVM_VERSION_MAJOR < 5 - , - NULL -#endif - ); -#if LLVM_VERSION_MAJOR < 9 - Function *cmplogGccStdStd = cast(c3); -#else - FunctionCallee cmplogGccStdStd = c3; -#endif + if (CmplogExtended) { + cmplogGccStdStd = + M.getOrInsertFunction("__cmplog_rtn_gcc_stdstring_stdstring_extended", + VoidTy, i8PtrTy, i8PtrTy); + } else { + cmplogGccStdStd = M.getOrInsertFunction( + "__cmplog_rtn_gcc_stdstring_stdstring", VoidTy, i8PtrTy, i8PtrTy); + } -#if LLVM_VERSION_MAJOR < 9 - Constant * -#else - FunctionCallee -#endif - c4 = M.getOrInsertFunction("__cmplog_rtn_gcc_stdstring_cstring", VoidTy, - i8PtrTy, i8PtrTy -#if LLVM_VERSION_MAJOR < 5 - , - NULL -#endif - ); -#if LLVM_VERSION_MAJOR < 9 - Function *cmplogGccStdC = cast(c4); -#else - FunctionCallee cmplogGccStdC = c4; -#endif + if (CmplogExtended) { + cmplogGccStdC = + M.getOrInsertFunction("__cmplog_rtn_gcc_stdstring_cstring_extended", + VoidTy, i8PtrTy, i8PtrTy); + } else { + cmplogGccStdC = M.getOrInsertFunction("__cmplog_rtn_gcc_stdstring_cstring", + VoidTy, i8PtrTy, i8PtrTy); + } -#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 (CmplogExtended) { + cmplogHookFnN = M.getOrInsertFunction("__cmplog_rtn_hook_n_extended", + VoidTy, i8PtrTy, i8PtrTy, Int64Ty); + } else { + cmplogHookFnN = M.getOrInsertFunction("__cmplog_rtn_hook_n", VoidTy, + i8PtrTy, i8PtrTy, Int64Ty); + } -#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 (CmplogExtended) { + cmplogHookFnStrN = M.getOrInsertFunction("__cmplog_rtn_hook_strn_extended", + VoidTy, i8PtrTy, i8PtrTy, Int64Ty); + } else { + cmplogHookFnStrN = M.getOrInsertFunction("__cmplog_rtn_hook_strn", VoidTy, + i8PtrTy, i8PtrTy, Int64Ty); + } -#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 + if (CmplogExtended) { + cmplogHookFnStr = M.getOrInsertFunction("__cmplog_rtn_hook_str_extended", + VoidTy, i8PtrTy, i8PtrTy); + } else { + cmplogHookFnStr = M.getOrInsertFunction("__cmplog_rtn_hook_str", VoidTy, + i8PtrTy, i8PtrTy); + } /* iterate over all functions, bbs and instruction and add suitable calls */ for (auto &F : M) { @@ -613,4 +550,4 @@ static RegisterStandardPasses RegisterCmpLogRoutinesPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCmpLogRoutinesPass); -#endif +#endif \ No newline at end of file diff --git a/libafl_cc/src/cmplog-switches-pass.cc b/libafl_cc/src/cmplog-switches-pass.cc deleted file mode 100644 index 24a72909d2..0000000000 --- a/libafl_cc/src/cmplog-switches-pass.cc +++ /dev/null @@ -1,327 +0,0 @@ -/* - american fuzzy lop++ - LLVM CmpLog instrumentation - -------------------------------------------------- - - Written by Andrea Fioraldi - - Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2020 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: - - http://www.apache.org/licenses/LICENSE-2.0 - -*/ - -#include -#include -#ifndef _WIN32 - #include - #include -#endif - -#include -#include -#include - -#include "common-llvm.h" - -#include "llvm/ADT/Statistic.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/Utils/BasicBlockUtils.h" -#include "llvm/Pass.h" -#include "llvm/Analysis/ValueTracking.h" - -#if LLVM_VERSION_MAJOR > 3 || \ - (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 - -using namespace llvm; - -static cl::opt CmplogExtended("cmplog_switches_extended", - cl::desc("Uses extended header"), - cl::init(false), cl::NotHidden); -namespace { - -#if USE_NEW_PM -class CmpLogSwitches : public PassInfoMixin { - public: - CmpLogSwitches() { -#else - -class CmpLogSwitches : public ModulePass { - public: - static char ID; - CmpLogSwitches() : ModulePass(ID) { -#endif - } - -#if USE_NEW_PM - PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); -#else - bool runOnModule(Module &M) override; - - #if LLVM_VERSION_MAJOR < 4 - const char *getPassName() const override { - #else - StringRef getPassName() const override { - #endif - return "cmplog switches"; - } -#endif - - private: - bool hookInstrs(Module &M); -}; - -} // namespace - -#if USE_NEW_PM -extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK -llvmGetPassPluginInfo() { - return {LLVM_PLUGIN_API_VERSION, "CmpLogSwitches", "v0.1", - [](PassBuilder &PB) { - #if LLVM_VERSION_MAJOR <= 13 - using OptimizationLevel = typename PassBuilder::OptimizationLevel; - #endif - PB.registerOptimizerLastEPCallback( - [](ModulePassManager &MPM, OptimizationLevel OL) { - MPM.addPass(CmpLogSwitches()); - }); - }}; -} -#else -char CmpLogSwitches::ID = 0; -#endif - -template -Iterator Unique(Iterator first, Iterator last) { - while (first != last) { - Iterator next(first); - last = std::remove(++next, last, *first); - first = next; - } - - return last; -} - -bool CmpLogSwitches::hookInstrs(Module &M) { - std::vector switches; - LLVMContext &C = M.getContext(); - - Type *VoidTy = Type::getVoidTy(C); - IntegerType *Int8Ty = IntegerType::getInt8Ty(C); - IntegerType *Int16Ty = IntegerType::getInt16Ty(C); - IntegerType *Int32Ty = IntegerType::getInt32Ty(C); - IntegerType *Int64Ty = IntegerType::getInt64Ty(C); - - FunctionCallee cmplogHookIns1; - FunctionCallee cmplogHookIns2; - FunctionCallee cmplogHookIns4; - FunctionCallee cmplogHookIns8; - - if (CmplogExtended) { - cmplogHookIns1 = M.getOrInsertFunction("__cmplog_ins_hook1_extended", - VoidTy, Int8Ty, Int8Ty, Int8Ty); - } else { - cmplogHookIns1 = M.getOrInsertFunction("__cmplog_ins_hook1", VoidTy, Int8Ty, - Int8Ty, Int8Ty); - } - - if (CmplogExtended) { - cmplogHookIns2 = M.getOrInsertFunction("__cmplog_ins_hook2_extended", - VoidTy, Int16Ty, Int16Ty, Int8Ty); - } else { - cmplogHookIns2 = M.getOrInsertFunction("__cmplog_ins_hook2", VoidTy, - Int16Ty, Int16Ty, Int8Ty); - } - - if (CmplogExtended) { - cmplogHookIns4 = M.getOrInsertFunction("__cmplog_ins_hook4_extended", - VoidTy, Int32Ty, Int32Ty, Int8Ty); - } else { - cmplogHookIns4 = M.getOrInsertFunction("__cmplog_ins_hook4", VoidTy, - Int32Ty, Int32Ty, Int8Ty); - } - - if (CmplogExtended) { - cmplogHookIns8 = M.getOrInsertFunction("__cmplog_ins_hook8_extended", - VoidTy, Int64Ty, Int64Ty, Int8Ty); - } else { - cmplogHookIns8 = M.getOrInsertFunction("__cmplog_ins_hook8", VoidTy, - Int64Ty, Int64Ty, Int8Ty); - } - - for (auto &F : M) { - if (isIgnoreFunction(&F)) { continue; } - - for (auto &BB : F) { - SwitchInst *switchInst = nullptr; - if ((switchInst = dyn_cast(BB.getTerminator()))) { - if (switchInst->getNumCases() > 1) { switches.push_back(switchInst); } - } - } - } - - switches.erase(Unique(switches.begin(), switches.end()), switches.end()); - - if (switches.size()) { - for (auto &SI : switches) { - Value *Val = SI->getCondition(); - unsigned int max_size = Val->getType()->getIntegerBitWidth(); - unsigned int cast_size; - unsigned char do_cast = 0; - - if (!SI->getNumCases() || max_size < 16) { - // skipping trivial switch - continue; - } - - if (max_size % 8) { - max_size = (((max_size / 8) + 1) * 8); - do_cast = 1; - } - - if (max_size > 128) { - // can't handle this - - max_size = 128; - do_cast = 1; - } - - IRBuilder<> IRB(SI->getParent()); - IRB.SetInsertPoint(SI); - - switch (max_size) { - case 8: - case 16: - case 32: - case 64: - case 128: - cast_size = max_size; - break; - default: - cast_size = 128; - do_cast = 1; - } - - // The predicate of the switch clause - Value *CompareTo = Val; - if (do_cast) { - CompareTo = - IRB.CreateIntCast(CompareTo, IntegerType::get(C, cast_size), false); - } - - for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e; - ++i) { - // Who uses LLVM Major < 5?? :p - ConstantInt *cint = i->getCaseValue(); - - if (cint) { - std::vector args; - args.push_back(CompareTo); - - Value *new_param = cint; - if (do_cast) { - new_param = - IRB.CreateIntCast(cint, IntegerType::get(C, cast_size), false); - } - - if (new_param) { - args.push_back(new_param); - if (CmplogExtended) { - ConstantInt *attribute = ConstantInt::get(Int8Ty, 1); - args.push_back(attribute); - } - if (cast_size != max_size) { - // not 8, 16, 32, 64, 128. - ConstantInt *bitsize = - ConstantInt::get(Int8Ty, (max_size / 8) - 1); - args.push_back(bitsize); // we have the arg for size in hookinsN - } - - switch (cast_size) { - case 8: - IRB.CreateCall(cmplogHookIns1, args); - break; - case 16: - IRB.CreateCall(cmplogHookIns2, args); - break; - case 32: - IRB.CreateCall(cmplogHookIns4, args); - break; - case 64: - IRB.CreateCall(cmplogHookIns8, args); - break; - case 128: -#ifdef WORD_SIZE_64 - if (max_size == 128) { - IRB.CreateCall(cmplogHookIns16, args); - - } else { - IRB.CreateCall(cmplogHookInsN, args); - } - -#endif - break; - default: - break; - } - } - } - } - } - } -} - -#if USE_NEW_PM -PreservedAnalyses CmpLogSwitches::run(Module &M, ModuleAnalysisManager &MAM) { -#else -bool CmpLogSwitches::runOnModule(Module &M) { -#endif - hookInstrs(M); - -#if USE_NEW_PM - auto PA = PreservedAnalyses::all(); -#endif - verifyModule(M); - -#if USE_NEW_PM - return PA; -#else - return true; -#endif -} - -#if USE_NEW_PM -#else -static void registerCmpLogSwitchesPass(const PassManagerBuilder &, - legacy::PassManagerBase &PM) { - auto p = new CmpLogSwitches(); - PM.add(p); -} - -static RegisterStandardPasses RegisterCmpLogSwitchesPass( - PassManagerBuilder::EP_OptimizerLast, registerCmpLogSwitchesPass); - -static RegisterStandardPasses RegisterCmpLogSwitchesPass0( - PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogSwitchesPass); - -static RegisterStandardPasses RegisterCmpLogSwitchesPassLTO( - PassManagerBuilder::EP_FullLinkTimeOptimizationLast, - registerCmpLogSwitchesPass); - -#endif diff --git a/libafl_cc/src/no-link-rt.c b/libafl_cc/src/no-link-rt.c index cd12c39247..daaddae2a4 100644 --- a/libafl_cc/src/no-link-rt.c +++ b/libafl_cc/src/no-link-rt.c @@ -56,7 +56,7 @@ void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2) { (void)arg2; } -#if !defined(_WIN32) && defined(__SIZEOF_INT128__) +#ifndef _WIN32 void __cmplog_ins_hook16_extended(uint128_t arg1, uint128_t arg2, uint8_t attr) { (void)attr; @@ -86,6 +86,10 @@ void __cmplog_rtn_hook(uint8_t *ptr1, uint8_t *ptr2) { (void)ptr1; (void)ptr2; } +void __cmplog_rtn_hook_extended(uint8_t *ptr1, uint8_t *ptr2) { + (void)ptr1; + (void)ptr2; +} void __cmplog_rtn_hook_n(const uint8_t *ptr1, const uint8_t *ptr2, uint64_t len) { @@ -93,36 +97,72 @@ void __cmplog_rtn_hook_n(const uint8_t *ptr1, const uint8_t *ptr2, (void)ptr2; (void)len; } +void __cmplog_rtn_hook_n_extended(const uint8_t *ptr1, const uint8_t *ptr2, + uint64_t len) { + (void)ptr1; + (void)ptr2; + (void)len; +} void __cmplog_rtn_hook_str(const uint8_t *ptr1, uint8_t *ptr2) { (void)ptr1; (void)ptr2; } +void __cmplog_rtn_hook_str_extended(const uint8_t *ptr1, uint8_t *ptr2) { + (void)ptr1; + (void)ptr2; +} void __cmplog_rtn_hook_strn(uint8_t *ptr1, uint8_t *ptr2, uint64_t len) { (void)ptr1; (void)ptr2; (void)len; } +void __cmplog_rtn_hook_strn_extended(uint8_t *ptr1, uint8_t *ptr2, + uint64_t len) { + (void)ptr1; + (void)ptr2; + (void)len; +} void __cmplog_rtn_gcc_stdstring_cstring(uint8_t *stdstring, uint8_t *cstring) { (void)stdstring; (void)cstring; } +void __cmplog_rtn_gcc_stdstring_cstring_extended(uint8_t *stdstring, + uint8_t *cstring) { + (void)stdstring; + (void)cstring; +} void __cmplog_rtn_gcc_stdstring_stdstring(uint8_t *stdstring1, uint8_t *stdstring2) { (void)stdstring1; (void)stdstring2; } +void __cmplog_rtn_gcc_stdstring_stdstring_extended(uint8_t *stdstring1, + uint8_t *stdstring2) { + (void)stdstring1; + (void)stdstring2; +} void __cmplog_rtn_llvm_stdstring_cstring(uint8_t *stdstring, uint8_t *cstring) { (void)stdstring; (void)cstring; } +void __cmplog_rtn_llvm_stdstring_cstring_extended(uint8_t *stdstring, + uint8_t *cstring) { + (void)stdstring; + (void)cstring; +} void __cmplog_rtn_llvm_stdstring_stdstring(uint8_t *stdstring1, uint8_t *stdstring2) { (void)stdstring1; (void)stdstring2; } +void __cmplog_rtn_llvm_stdstring_stdstring_extended(uint8_t *stdstring1, + uint8_t *stdstring2) { + (void)stdstring1; + (void)stdstring2; +} diff --git a/libafl_targets/Cargo.toml b/libafl_targets/Cargo.toml index 4a15f53792..d9af7efde4 100644 --- a/libafl_targets/Cargo.toml +++ b/libafl_targets/Cargo.toml @@ -53,6 +53,7 @@ cmplog = ["common"] # Compile C code defining cmp log maps forkserver = ["common"] # Compile C code for forkserver support windows_asan = ["common"] # Compile C code for ASAN on Windows whole_archive = [] # use +whole-archive to ensure the presence of weak symbols +cmplog_extended_instrumentation = [] # support for aflpp cmplog map, we will remove this once aflpp and libafl cmplog shares the same LLVM passes. [build-dependencies] bindgen = "0.68" diff --git a/libafl_targets/build.rs b/libafl_targets/build.rs index 86e3cd32b4..09f2f2059b 100644 --- a/libafl_targets/build.rs +++ b/libafl_targets/build.rs @@ -18,12 +18,6 @@ fn main() { let cmp_map_size: usize = option_env!("LIBAFL_CMP_MAP_SIZE") .map_or(Ok(65536), str::parse) .expect("Could not parse LIBAFL_CMP_MAP_SIZE"); - let aflpp_cmplog_map_w: usize = option_env!("LIBAFL_AFLPP_CMPLOG_MAP_W") - .map_or(Ok(65536), str::parse) - .expect("Could not parse LIBAFL_AFLPP_CMPLOG_MAP_W"); - let aflpp_cmplog_map_h: usize = option_env!("LIBAFL_AFLPP_CMPLOG_MAP_W") - .map_or(Ok(32), str::parse) - .expect("Could not parse LIBAFL_AFLPP_CMPLOG_MAP_W"); let cmplog_map_w: usize = option_env!("LIBAFL_CMPLOG_MAP_W") .map_or(Ok(65536), str::parse) .expect("Could not parse LIBAFL_CMPLOG_MAP_W"); @@ -42,10 +36,6 @@ fn main() { pub const EDGES_MAP_SIZE: usize = {edges_map_size}; /// The size of the cmps map pub const CMP_MAP_SIZE: usize = {cmp_map_size}; - /// The width of the aflpp cmplog map - pub const AFLPP_CMPLOG_MAP_W: usize = {aflpp_cmplog_map_w}; - /// The height of the aflpp cmplog map - pub const AFLPP_CMPLOG_MAP_H: usize = {aflpp_cmplog_map_h}; /// The width of the `CmpLog` map pub const CMPLOG_MAP_W: usize = {cmplog_map_w}; /// The height of the `CmpLog` map @@ -58,8 +48,6 @@ fn main() { println!("cargo:rerun-if-env-changed=LIBAFL_EDGES_MAP_SIZE"); println!("cargo:rerun-if-env-changed=LIBAFL_CMP_MAP_SIZE"); - println!("cargo:rerun-if-env-changed=LIBAFL_AFLPP_CMPLOG_MAP_W"); - println!("cargo:rerun-if-env-changed=LIBAFL_AFLPP_CMPLOG_MAP_H"); println!("cargo:rerun-if-env-changed=LIBAFL_CMPLOG_MAP_W"); println!("cargo:rerun-if-env-changed=LIBAFL_CMPLOG_MAP_H"); println!("cargo:rerun-if-env-changed=LIBAFL_ACCOUNTING_MAP_SIZE"); @@ -107,14 +95,6 @@ fn main() { sancov_cmp .define("CMP_MAP_SIZE", Some(&*format!("{cmp_map_size}"))) - .define( - "AFLPP_CMPLOG_MAP_W", - Some(&*format!("{aflpp_cmplog_map_w}")), - ) - .define( - "AFLPP_CMPLOG_MAP_H", - Some(&*format!("{aflpp_cmplog_map_h}")), - ) .define("CMPLOG_MAP_W", Some(&*format!("{cmplog_map_w}"))) .define("CMPLOG_MAP_H", Some(&*format!("{cmplog_map_h}"))) .file(src_dir.join("sancov_cmp.c")) @@ -166,18 +146,14 @@ fn main() { #[cfg(unix)] { - cc::Build::new() - .flag("-Wno-pointer-sign") // UNIX ONLY FLAGS + let mut cc = cc::Build::new(); + + #[cfg(feature = "cmplog_extended_instrumentation")] + cc.define("CMPLOG_EXTENDED", Some("1")); + + cc.flag("-Wno-pointer-sign") // UNIX ONLY FLAGS .flag("-Wno-sign-compare") .define("CMP_MAP_SIZE", Some(&*format!("{cmp_map_size}"))) - .define( - "AFLPP_CMPLOG_MAP_W", - Some(&*format!("{aflpp_cmplog_map_w}")), - ) - .define( - "AFLPP_CMPLOG_MAP_H", - Some(&*format!("{aflpp_cmplog_map_h}")), - ) .define("CMPLOG_MAP_W", Some(&*format!("{cmplog_map_w}"))) .define("CMPLOG_MAP_H", Some(&*format!("{cmplog_map_h}"))) .file(src_dir.join("cmplog.c")) @@ -188,14 +164,6 @@ fn main() { { cc::Build::new() .define("CMP_MAP_SIZE", Some(&*format!("{cmp_map_size}"))) - .define( - "AFLPP_CMPLOG_MAP_W", - Some(&*format!("{aflpp_cmplog_map_w}")), - ) - .define( - "AFLPP_CMPLOG_MAP_H", - Some(&*format!("{aflpp_cmplog_map_h}")), - ) .define("CMPLOG_MAP_W", Some(&*format!("{cmplog_map_w}"))) .define("CMPLOG_MAP_H", Some(&*format!("{cmplog_map_h}"))) .file(src_dir.join("cmplog.c")) diff --git a/libafl_targets/src/cmplog.c b/libafl_targets/src/cmplog.c index 3eefa30eea..659ef0dadd 100644 --- a/libafl_targets/src/cmplog.c +++ b/libafl_targets/src/cmplog.c @@ -37,8 +37,10 @@ __attribute__((weak)) void *__asan_region_is_poisoned(const void *beg, #endif -CmpLogMap *libafl_cmplog_map_ptr = &libafl_cmplog_map; +CmpLogMap *libafl_cmplog_map_ptr = &libafl_cmplog_map; +#ifdef CMPLOG_EXTENDED CmpLogMapExtended *libafl_cmplog_map_extended_ptr = &libafl_cmplog_map_extended; +#endif void __libafl_targets_cmplog_instructions(uintptr_t k, uint8_t shape, uint64_t arg1, uint64_t arg2) { @@ -67,12 +69,14 @@ void __libafl_targets_cmplog_instructions(uintptr_t k, uint8_t shape, void __libafl_targets_cmplog_instructions_extended(uintptr_t k, uint8_t shape, uint64_t arg1, uint64_t arg2, uint8_t attr) { +#ifdef CMPLOG_EXTENDED if (!libafl_cmplog_enabled) { return; } libafl_cmplog_enabled = false; + // printf("%ld %ld %ld\n", k, arg1, arg2); uint16_t hits; - if (libafl_cmplog_map_extended_ptr->headers[k].type != CMPLOG_KIND_INS) { - libafl_cmplog_map_extended_ptr->headers[k].type = CMPLOG_KIND_INS; + if (libafl_cmplog_map_extended_ptr->headers[k].type != AFL_CMP_TYPE_INS) { + libafl_cmplog_map_extended_ptr->headers[k].type = AFL_CMP_TYPE_INS; libafl_cmplog_map_extended_ptr->headers[k].hits = 1; libafl_cmplog_map_extended_ptr->headers[k].shape = shape; hits = 0; @@ -88,6 +92,14 @@ void __libafl_targets_cmplog_instructions_extended(uintptr_t k, uint8_t shape, libafl_cmplog_map_extended_ptr->vals.operands[k][hits].v1 = arg2; libafl_cmplog_map_extended_ptr->headers[k].attribute = attr; libafl_cmplog_enabled = true; +#else + // just do nothing + (void)k; + (void)shape; + (void)arg1; + (void)arg2; + (void)attr; +#endif } // POSIX shenanigan to see if an area is mapped. @@ -161,6 +173,43 @@ void __libafl_targets_cmplog_routines_checked(uintptr_t k, const uint8_t *ptr1, libafl_cmplog_enabled = true; } +// cmplog routines after area check +void __libafl_targets_cmplog_routines_checked_extended(uintptr_t k, + const uint8_t *ptr1, + const uint8_t *ptr2, + size_t len) { +#ifdef CMPLOG_EXTENDED + libafl_cmplog_enabled = false; + uint32_t hits; + // printf("RTN: %ld %ld %ld %ld\n", k, *ptr1, *ptr2, len); + if (libafl_cmplog_map_extended_ptr->headers[k].type != AFL_CMP_TYPE_RTN) { + libafl_cmplog_map_extended_ptr->headers[k].type = AFL_CMP_TYPE_RTN; + libafl_cmplog_map_extended_ptr->headers[k].hits = 1; + libafl_cmplog_map_extended_ptr->headers[k].shape = len; + hits = 0; + } else { + hits = libafl_cmplog_map_extended_ptr->headers[k].hits++; + if (libafl_cmplog_map_extended_ptr->headers[k].shape < len) { + libafl_cmplog_map_extended_ptr->headers[k].shape = + len; // TODO; adjust len for AFL++'s cmplog protocol + } + } + + hits &= CMPLOG_MAP_RTN_H - 1; + libafl_cmplog_map_extended_ptr->vals.routines[k][hits].v0_len = len; + libafl_cmplog_map_extended_ptr->vals.routines[k][hits].v1_len = len; + MEMCPY(libafl_cmplog_map_extended_ptr->vals.routines[k][hits].v0, ptr1, len); + MEMCPY(libafl_cmplog_map_extended_ptr->vals.routines[k][hits].v1, ptr2, len); + libafl_cmplog_enabled = true; +#else + // just do nothing + (void)k; + (void)ptr1; + (void)ptr2; + (void)len; +#endif +} + // Very generic cmplog routines callback void __libafl_targets_cmplog_routines(uintptr_t k, const uint8_t *ptr1, const uint8_t *ptr2) { @@ -290,19 +339,51 @@ void __cmplog_ins_hookN(uint128_t arg1, uint128_t arg2, uint8_t size) { */ void __cmplog_rtn_hook(const uint8_t *ptr1, const uint8_t *ptr2) { + if (!libafl_cmplog_enabled) { return; } + + int l1, l2; + if ((l1 = area_is_valid(ptr1, CMPLOG_RTN_LEN)) <= 0 || + (l2 = area_is_valid(ptr2, CMPLOG_RTN_LEN)) <= 0) { + return; + } + int len = MIN(l1, l2); + uintptr_t k = RETADDR; k = (k >> 4) ^ (k << 8); k &= CMPLOG_MAP_W - 1; - __libafl_targets_cmplog_routines(k, ptr1, ptr2); + __libafl_targets_cmplog_routines_checked(k, ptr1, ptr2, len); +} + +void __cmplog_rtn_hook_extended(const uint8_t *ptr1, const uint8_t *ptr2) { + if (!libafl_cmplog_enabled) { return; } + + int l1, l2; + if ((l1 = area_is_valid(ptr1, CMPLOG_RTN_LEN)) <= 0 || + (l2 = area_is_valid(ptr2, CMPLOG_RTN_LEN)) <= 0) { + return; + } + int len = MIN(l1, l2); + + uintptr_t k = RETADDR; + k = (k >> 4) ^ (k << 8); + k &= CMPLOG_MAP_W - 1; + + __libafl_targets_cmplog_routines_checked_extended(k, ptr1, ptr2, len); } void __cmplog_rtn_hook_n(const uint8_t *ptr1, const uint8_t *ptr2, uint64_t len) { + // this code is from AFL++ + // but i don't know why afl++ just ignores the len argument (void)(len); __cmplog_rtn_hook(ptr1, ptr2); } - +void __cmplog_rtn_hook_n_extended(const uint8_t *ptr1, const uint8_t *ptr2, + uint64_t len) { + (void)(len); + __cmplog_rtn_hook_extended(ptr1, ptr2); +} /* hook for string functions, eg. strcmp, strcasecmp etc. */ void __cmplog_rtn_hook_str(const uint8_t *ptr1, uint8_t *ptr2) { if (!libafl_cmplog_enabled) { return; } @@ -325,6 +406,28 @@ void __cmplog_rtn_hook_str(const uint8_t *ptr1, uint8_t *ptr2) { __libafl_targets_cmplog_routines_checked(k, ptr1, ptr2, l); } +/* hook for string functions, eg. strcmp, strcasecmp etc. */ +void __cmplog_rtn_hook_str_extended(const uint8_t *ptr1, uint8_t *ptr2) { + if (!libafl_cmplog_enabled) { return; } + if (unlikely(!ptr1 || !ptr2)) return; + + // these strnlen could indeed fail. but if it fails here it will sigsegv in + // the following hooked function call anyways + int len1 = strnlen(ptr1, 30) + 1; + int len2 = strnlen(ptr2, 30) + 1; + int l = MAX(len1, len2); + + l = MIN(l, area_is_valid(ptr1, l + 1)); // can we really access it? check + l = MIN(l, area_is_valid(ptr2, l + 1)); // can we really access it? check + + if (l < 2) return; + + intptr_t k = RETADDR; + k = (k >> 4) ^ (k << 8); + k &= CMPLOG_MAP_W - 1; + + __libafl_targets_cmplog_routines_checked_extended(k, ptr1, ptr2, l); +} /* hook for string with length functions, eg. strncmp, strncasecmp etc. Note that we ignore the len parameter and take longer strings if present. */ @@ -350,10 +453,35 @@ void __cmplog_rtn_hook_strn(uint8_t *ptr1, uint8_t *ptr2, uint64_t len) { __libafl_targets_cmplog_routines_checked(k, ptr1, ptr2, l); } +/* hook for string with length functions, eg. strncmp, strncasecmp etc. + Note that we ignore the len parameter and take longer strings if present. */ +void __cmplog_rtn_hook_strn_extended(uint8_t *ptr1, uint8_t *ptr2, + uint64_t len) { + if (!libafl_cmplog_enabled) { return; } + if (unlikely(!ptr1 || !ptr2)) return; + + int len0 = MIN(len, 31); // cap by 31 + // these strnlen could indeed fail. but if it fails here it will sigsegv in + // the following hooked function call anyways + int len1 = strnlen(ptr1, len0); + int len2 = strnlen(ptr2, len0); + int l = MAX(len1, len2); + + l = MIN(l, area_is_valid(ptr1, l + 1)); // can we really access it? check + l = MIN(l, area_is_valid(ptr2, l + 1)); // can we really access it? check + + if (l < 2) return; + + intptr_t k = RETADDR; + k = (k >> 4) ^ (k << 8); + k &= CMPLOG_MAP_W - 1; + + __libafl_targets_cmplog_routines_checked_extended(k, ptr1, ptr2, l); +} // gcc libstdc++ // _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE7compareEPKc -static const uint8_t *get_gcc_stdstring(const uint8_t *string) { +static inline const uint8_t *get_gcc_stdstring(const uint8_t *string) { uint32_t *len = (uint32_t *)(string + 8); if (*len < 16) { // in structure @@ -366,7 +494,7 @@ static const uint8_t *get_gcc_stdstring(const uint8_t *string) { // llvm libc++ _ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocator // IcEEE7compareEmmPKcm -static const uint8_t *get_llvm_stdstring(const uint8_t *string) { +static inline const uint8_t *get_llvm_stdstring(const uint8_t *string) { // length is in: if ((string[0] & 1) == 0) {uint8_t len = (string[0] >> 1);} // or: if (string[0] & 1) {uint32_t *len = (uint32_t *) (string + 8);} @@ -399,6 +527,28 @@ void __cmplog_rtn_gcc_stdstring_cstring(const uint8_t *stdstring, k &= CMPLOG_MAP_W - 1; __libafl_targets_cmplog_routines_checked(k, string_ptr, cstring, len); } +void __cmplog_rtn_gcc_stdstring_cstring_extended(const uint8_t *stdstring, + const uint8_t *cstring) { + if (!libafl_cmplog_enabled) { return; } + // This gcc string structure has 32 bytes of content at max + // That's what 32 means! + if (area_is_valid(stdstring, 32) <= 0) { return; } + + int l1 = area_is_valid(cstring, CMPLOG_RTN_LEN); + if (l1 <= 0) { return; } + + const uint8_t *string_ptr = get_gcc_stdstring(stdstring); + int l2 = area_is_valid(string_ptr, CMPLOG_RTN_LEN); + if (l2 <= 0) { return; } + + int len = MIN(31, MIN(l1, l2)); + + uintptr_t k = RETADDR; + k = (k >> 4) ^ (k << 8); + k &= CMPLOG_MAP_W - 1; + __libafl_targets_cmplog_routines_checked_extended(k, string_ptr, cstring, + len); +} void __cmplog_rtn_gcc_stdstring_stdstring(const uint8_t *stdstring1, const uint8_t *stdstring2) { @@ -422,6 +572,29 @@ void __cmplog_rtn_gcc_stdstring_stdstring(const uint8_t *stdstring1, k &= CMPLOG_MAP_W - 1; __libafl_targets_cmplog_routines_checked(k, string_ptr1, string_ptr2, len); } +void __cmplog_rtn_gcc_stdstring_stdstring_extended(const uint8_t *stdstring1, + const uint8_t *stdstring2) { + if (!libafl_cmplog_enabled) { return; } + + if (area_is_valid(stdstring1, 32) <= 0) { return; }; + if (area_is_valid(stdstring2, 32) <= 0) { return; }; + + const uint8_t *string_ptr1 = get_gcc_stdstring(stdstring1); + int l1 = area_is_valid(string_ptr1, CMPLOG_RTN_LEN); + if (l1 <= 0) { return; } + + const uint8_t *string_ptr2 = get_gcc_stdstring(stdstring2); + int l2 = area_is_valid(string_ptr2, CMPLOG_RTN_LEN); + if (l2 <= 0) { return; } + + int len = MIN(31, MIN(l1, l2)); + + uintptr_t k = RETADDR; + k = (k >> 4) ^ (k << 8); + k &= CMPLOG_MAP_W - 1; + __libafl_targets_cmplog_routines_checked_extended(k, string_ptr1, string_ptr2, + len); +} void __cmplog_rtn_llvm_stdstring_cstring(const uint8_t *stdstring, const uint8_t *cstring) { @@ -443,6 +616,27 @@ void __cmplog_rtn_llvm_stdstring_cstring(const uint8_t *stdstring, k &= CMPLOG_MAP_W - 1; __libafl_targets_cmplog_routines_checked(k, string_ptr, cstring, len); } +void __cmplog_rtn_llvm_stdstring_cstring_extended(const uint8_t *stdstring, + const uint8_t *cstring) { + if (!libafl_cmplog_enabled) { return; } + + if (area_is_valid(stdstring, 32) <= 0) { return; } + + int l1 = area_is_valid(cstring, CMPLOG_RTN_LEN); + if (l1 <= 0) { return; } + + const uint8_t *string_ptr = get_llvm_stdstring(stdstring); + int l2 = area_is_valid(string_ptr, CMPLOG_RTN_LEN); + if (l2 <= 0) { return; } + + int len = MIN(31, MIN(l1, l2)); + + uintptr_t k = RETADDR; + k = (k >> 4) ^ (k << 8); + k &= CMPLOG_MAP_W - 1; + __libafl_targets_cmplog_routines_checked_extended(k, string_ptr, cstring, + len); +} void __cmplog_rtn_llvm_stdstring_stdstring(const uint8_t *stdstring1, const uint8_t *stdstring2) { @@ -466,3 +660,26 @@ void __cmplog_rtn_llvm_stdstring_stdstring(const uint8_t *stdstring1, k &= CMPLOG_MAP_W - 1; __libafl_targets_cmplog_routines_checked(k, string_ptr1, string_ptr2, len); } +void __cmplog_rtn_llvm_stdstring_stdstring_extended(const uint8_t *stdstring1, + const uint8_t *stdstring2) { + if (!libafl_cmplog_enabled) { return; } + + if (area_is_valid(stdstring1, 32) <= 0) { return; }; + if (area_is_valid(stdstring2, 32) <= 0) { return; }; + + const uint8_t *string_ptr1 = get_gcc_stdstring(stdstring1); + int l1 = area_is_valid(get_gcc_stdstring(stdstring1), CMPLOG_RTN_LEN); + if (l1 <= 0) { return; } + + const uint8_t *string_ptr2 = get_gcc_stdstring(stdstring2); + int l2 = area_is_valid(get_gcc_stdstring(stdstring2), CMPLOG_RTN_LEN); + if (l2 <= 0) { return; } + + int len = MIN(31, MIN(l1, l2)); + + uintptr_t k = RETADDR; + k = (k >> 4) ^ (k << 8); + k &= CMPLOG_MAP_W - 1; + __libafl_targets_cmplog_routines_checked_extended(k, string_ptr1, string_ptr2, + len); +} \ No newline at end of file diff --git a/libafl_targets/src/cmplog.h b/libafl_targets/src/cmplog.h index 75a91ab893..ae37f2559f 100644 --- a/libafl_targets/src/cmplog.h +++ b/libafl_targets/src/cmplog.h @@ -11,14 +11,26 @@ #define CMPLOG_MAP_H 32 #endif -#define CMPLOG_RTN_LEN 32 +// difference between aflpp and libafl +#ifdef CMPLOG_EXTENDED + #define CMPLOG_RTN_LEN 31 +#else + #define CMPLOG_RTN_LEN 32 +#endif #define CMPLOG_MAP_RTN_H \ ((CMPLOG_MAP_H * sizeof(CmpLogInstruction)) / sizeof(CmpLogRoutine)) +#define CMPLOG_MAP_RTN_EXTENDED_H \ + ((CMPLOG_MAP_H * sizeof(CmpLogInstructionExtended)) / sizeof(CmpLogRoutine)) + #define CMPLOG_KIND_INS 0 #define CMPLOG_KIND_RTN 1 +// Same, difference between aflpp and libafl +#define AFL_CMP_TYPE_INS 1 +#define AFL_CMP_TYPE_RTN 2 + typedef struct CmpLogHeader { uint16_t hits; uint8_t shape; @@ -53,11 +65,25 @@ typedef struct CmpLogInstruction { uint64_t v1; } CmpLogInstruction; +typedef struct CmpLogInstructionExtended { + uint64_t v0; + uint64_t v1; + uint64_t v0_128; + uint64_t v1_128; +} CmpLogInstructionExtended; + typedef struct CmpLogRoutine { uint8_t v0[CMPLOG_RTN_LEN]; uint8_t v1[CMPLOG_RTN_LEN]; } CmpLogRoutine; +typedef struct CmpLogRoutineExtended { + uint8_t v0[CMPLOG_RTN_LEN]; + uint8_t v0_len; + uint8_t v1[CMPLOG_RTN_LEN]; + uint8_t v1_len; +} CmpLogRoutineExtended; + typedef struct CmpLogMap { CmpLogHeader headers[CMPLOG_MAP_W]; union { @@ -69,8 +95,8 @@ typedef struct CmpLogMap { typedef struct CmpLogMapExtended { CmpLogHeaderExtended headers[CMPLOG_MAP_W]; union { - CmpLogInstruction operands[CMPLOG_MAP_W][CMPLOG_MAP_H]; - CmpLogRoutine routines[CMPLOG_MAP_W][CMPLOG_MAP_RTN_H]; + CmpLogInstructionExtended operands[CMPLOG_MAP_W][CMPLOG_MAP_H]; + CmpLogRoutineExtended routines[CMPLOG_MAP_W][CMPLOG_MAP_RTN_EXTENDED_H]; } vals; } CmpLogMapExtended; diff --git a/libafl_targets/src/cmps/mod.rs b/libafl_targets/src/cmps/mod.rs index 155674dbea..b59171b5df 100644 --- a/libafl_targets/src/cmps/mod.rs +++ b/libafl_targets/src/cmps/mod.rs @@ -17,7 +17,7 @@ use libafl::{ use serde::{Deserialize, Deserializer, Serialize, Serializer}; pub use stages::*; -use crate::{AFLPP_CMPLOG_MAP_H, AFLPP_CMPLOG_MAP_W, CMPLOG_MAP_H, CMPLOG_MAP_W}; +use crate::{CMPLOG_MAP_H, CMPLOG_MAP_W}; // CONSTANTS @@ -31,14 +31,16 @@ pub const CMPLOG_RTN_LEN: usize = 32; pub const CMPLOG_MAP_RTN_H: usize = (CMPLOG_MAP_H * core::mem::size_of::()) / core::mem::size_of::(); +/// The height of extended rountine map +pub const CMPLOG_MAP_RTN_EXTENDED_H: usize = CMPLOG_MAP_H + * core::mem::size_of::() + / core::mem::size_of::(); + /// `CmpLog` instruction kind pub const CMPLOG_KIND_INS: u8 = 0; /// `CmpLog` routine kind pub const CMPLOG_KIND_RTN: u8 = 1; -/// The height for RTN -pub const AFL_CMPLOG_MAP_RTN_H: usize = AFLPP_CMPLOG_MAP_H / 2; - /// The AFL++ `CMP_TYPE_INS` pub const AFL_CMP_TYPE_INS: u32 = 1; /// The AFL++ `CMP_TYPE_RTN` @@ -269,8 +271,8 @@ impl Debug for CmpLogVals { #[repr(C, packed)] /// Comparison values pub union AFLppCmpLogVals { - operands: [[AFLppCmpLogOperands; AFLPP_CMPLOG_MAP_H]; AFLPP_CMPLOG_MAP_W], - fn_operands: [[AFLppCmpLogFnOperands; AFL_CMPLOG_MAP_RTN_H]; AFLPP_CMPLOG_MAP_W], + operands: [[AFLppCmpLogOperands; CMPLOG_MAP_H]; CMPLOG_MAP_W], + fn_operands: [[AFLppCmpLogFnOperands; CMPLOG_MAP_RTN_EXTENDED_H]; CMPLOG_MAP_W], } impl Debug for AFLppCmpLogVals { @@ -282,15 +284,13 @@ impl Debug for AFLppCmpLogVals { impl AFLppCmpLogVals { #[must_use] /// Reference comparison values as comparison operands - pub fn operands(&self) -> &[[AFLppCmpLogOperands; AFLPP_CMPLOG_MAP_H]; AFLPP_CMPLOG_MAP_W] { + pub fn operands(&self) -> &[[AFLppCmpLogOperands; CMPLOG_MAP_H]; CMPLOG_MAP_W] { unsafe { &self.operands } } #[must_use] /// Mutably reference comparison values as comparison operands - pub fn operands_mut( - &mut self, - ) -> &mut [[AFLppCmpLogOperands; AFLPP_CMPLOG_MAP_H]; AFLPP_CMPLOG_MAP_W] { + pub fn operands_mut(&mut self) -> &mut [[AFLppCmpLogOperands; CMPLOG_MAP_H]; CMPLOG_MAP_W] { unsafe { &mut self.operands } } @@ -298,7 +298,7 @@ impl AFLppCmpLogVals { /// Reference comparison values as comparison function operands pub fn fn_operands( &self, - ) -> &[[AFLppCmpLogFnOperands; AFL_CMPLOG_MAP_RTN_H]; AFLPP_CMPLOG_MAP_W] { + ) -> &[[AFLppCmpLogFnOperands; CMPLOG_MAP_RTN_EXTENDED_H]; CMPLOG_MAP_W] { unsafe { &self.fn_operands } } @@ -306,7 +306,7 @@ impl AFLppCmpLogVals { /// Mutably reference comparison values as comparison function operands pub fn fn_operands_mut( &mut self, - ) -> &mut [[AFLppCmpLogFnOperands; AFL_CMPLOG_MAP_RTN_H]; AFLPP_CMPLOG_MAP_W] { + ) -> &mut [[AFLppCmpLogFnOperands; CMPLOG_MAP_RTN_EXTENDED_H]; CMPLOG_MAP_W] { unsafe { &mut self.fn_operands } } } @@ -412,6 +412,7 @@ pub static mut libafl_cmplog_map: CmpLogMap = CmpLogMap { /// The globale `CmpLog` map, aflpp style #[no_mangle] +#[cfg(feature = "cmplog_extended_instrumentation")] #[allow(clippy::large_stack_arrays)] pub static mut libafl_cmplog_map_extended: AFLppCmpLogMap = AFLppCmpLogMap { headers: [AFLppCmpLogHeader { data: [0; 8] }; CMPLOG_MAP_W], @@ -426,13 +427,14 @@ pub static mut libafl_cmplog_map_extended: AFLppCmpLogMap = AFLppCmpLogMap { }; pub use libafl_cmplog_map as CMPLOG_MAP; +#[cfg(feature = "cmplog_extended_instrumentation")] pub use libafl_cmplog_map_extended as CMPLOG_MAP_EXTENDED; #[derive(Debug, Clone)] #[repr(C, packed)] /// Comparison map compatible with AFL++ cmplog instrumentation pub struct AFLppCmpLogMap { - headers: [AFLppCmpLogHeader; AFLPP_CMPLOG_MAP_W], + headers: [AFLppCmpLogHeader; CMPLOG_MAP_W], vals: AFLppCmpLogVals, } @@ -500,7 +502,7 @@ impl<'de> Deserialize<'de> for AFLppCmpLogMap { impl CmpMap for AFLppCmpLogMap { fn len(&self) -> usize { - AFLPP_CMPLOG_MAP_W + CMPLOG_MAP_W } fn executions_for(&self, idx: usize) -> usize { @@ -509,15 +511,15 @@ impl CmpMap for AFLppCmpLogMap { fn usable_executions_for(&self, idx: usize) -> usize { if self.headers[idx]._type() == AFL_CMP_TYPE_INS { - if self.executions_for(idx) < AFLPP_CMPLOG_MAP_H { + if self.executions_for(idx) < CMPLOG_MAP_H { self.executions_for(idx) } else { - AFLPP_CMPLOG_MAP_H + CMPLOG_MAP_H } - } else if self.executions_for(idx) < AFL_CMPLOG_MAP_RTN_H { + } else if self.executions_for(idx) < CMPLOG_MAP_RTN_H { self.executions_for(idx) } else { - AFL_CMPLOG_MAP_RTN_H + CMPLOG_MAP_RTN_H } } diff --git a/libafl_targets/src/cmps/observers/aflpp.rs b/libafl_targets/src/cmps/observers/aflpp.rs index 20a5d8e30a..7dd125e2bd 100644 --- a/libafl_targets/src/cmps/observers/aflpp.rs +++ b/libafl_targets/src/cmps/observers/aflpp.rs @@ -18,6 +18,8 @@ use libafl_bolts::{ownedref::OwnedRefMut, Named}; use serde::{Deserialize, Serialize}; use crate::cmps::AFLppCmpLogMap; +#[cfg(feature = "cmplog_extended_instrumentation")] +use crate::cmps::CMPLOG_ENABLED; /* From AFL++ cmplog.h @@ -147,6 +149,16 @@ where S: UsesInput + Debug + HasMetadata, { fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> { + #[cfg(feature = "cmplog_extended_instrumentation")] + unsafe { + // if the target is compiled with aflpp and you are running forkserver then this is not needed + // because with forkserver, you have two executors (processes), one is dedicated for edge-cov + // the other dedicated for cmplog. + // however if it is in-process, then cmplog instrumentation is in the same binary as the edge-cov binary + // (so we only have one executable) + // therefore we need to turn this thing on and off to change this according to what executors we are using + CMPLOG_ENABLED = 1; + } self.cmp_map.as_mut().reset()?; Ok(()) } @@ -157,6 +169,10 @@ where _input: &S::Input, _exit_kind: &ExitKind, ) -> Result<(), Error> { + #[cfg(feature = "cmplog_extended_instrumentation")] + unsafe { + CMPLOG_ENABLED = 0; + } if self.add_meta { self.add_cmpvalues_meta(state); } @@ -295,6 +311,18 @@ impl<'a> CmpObserverMetadata<'a, AFLppCmpLogMap> for AFLppCmpValuesMetadata { } else { // push into new_cmpvals // println!("Adding to new_cmpvals"); + /* + unsafe { + println!( + "idx {:#?} type {:#?} sz {:#?} ptr1 {:p} val1 {:x}", + i, + cmp_map.headers()[i]._type(), + cmp_map.headers()[i].shape(), + &cmp_map.vals.operands[i][0], + cmp_map.vals.operands[i][0].v0(), + ); + } + */ for j in 0..execs { if let Some(val) = cmp_map.values_of(i, j) { cmp_values.push(val);