Merge pull request #1628 from AFLplusplus/dev

Dev
This commit is contained in:
van Hauser
2023-01-27 13:40:48 +01:00
committed by GitHub
24 changed files with 407 additions and 350 deletions

4
.gitignore vendored
View File

@ -83,6 +83,10 @@ examples/aflpp_driver/libAFLQemuDriver.a
libAFLDriver.a libAFLDriver.a
libAFLQemuDriver.a libAFLQemuDriver.a
test/.afl_performance test/.afl_performance
test-instr
test/output
test/test-instr.ts
test/test-persistent
gmon.out gmon.out
afl-frida-trace.so afl-frida-trace.so
utils/afl_network_proxy/afl-network-client utils/afl_network_proxy/afl-network-client

View File

@ -48,6 +48,7 @@ LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[0-2]\.|^3.[0-7]\.' && echo 1 || echo 0 ) LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[0-2]\.|^3.[0-7]\.' && echo 1 || echo 0 )
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[5-9]' && echo 1 || echo 0 ) LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[5-9]' && echo 1 || echo 0 )
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[0-9]' && echo 1 || echo 0 ) LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[0-9]' && echo 1 || echo 0 )
LLVM_NEWER_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[6-9]' && echo 1 || echo 0 )
LLVM_10_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[1-9]|^10\.[1-9]|^10\.0.[1-9]' && echo 1 || echo 0 ) LLVM_10_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[1-9]|^10\.[1-9]|^10\.0.[1-9]' && echo 1 || echo 0 )
LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[1-9]' && echo 1 || echo 0 ) LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[1-9]' && echo 1 || echo 0 )
LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null) LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
@ -81,6 +82,11 @@ ifeq "$(LLVM_NEW_API)" "1"
LLVM_TOO_OLD=0 LLVM_TOO_OLD=0
endif endif
ifeq "$(LLVM_NEWER_API)" "1"
$(info [+] llvm_mode detected llvm 16+, enabling c++17)
LLVM_STDCXX = c++17
endif
ifeq "$(LLVM_TOO_OLD)" "1" ifeq "$(LLVM_TOO_OLD)" "1"
$(info [!] llvm_mode detected an old version of llvm, upgrade to at least 9 or preferable 11!) $(info [!] llvm_mode detected an old version of llvm, upgrade to at least 9 or preferable 11!)
$(shell sleep 1) $(shell sleep 1)

View File

@ -3,6 +3,18 @@
This is the list of all noteworthy changes made in every public This is the list of all noteworthy changes made in every public
release of the tool. See README.md for the general instruction manual. release of the tool. See README.md for the general instruction manual.
### Version ++4.06a (dev)
- afl-fuzz:
- ensure temporary file descriptor is closed when not used
- afl-cc:
- add CFI sanitizer variant to gcc targets
- llvm 16 support (thanks to @devnexen!)
- support llvm 15 native pcguard changes
- better sanitizer default options support for all tools
- unicorn_mode: updated and minor issues fixed
- frida_mode: fix issue on MacOS
- more minor fixes
### Version ++4.05c (release) ### Version ++4.05c (release)
- MacOS: libdislocator, libtokencap etc. do not work with modern - MacOS: libdislocator, libtokencap etc. do not work with modern
MacOS anymore, but could be patched to work, see this issue if you MacOS anymore, but could be patched to work, see this issue if you
@ -20,6 +32,7 @@
- `-t none` now translates to `-t 120000` (120 seconds) - `-t none` now translates to `-t 120000` (120 seconds)
- unicorn_mode updated - unicorn_mode updated
- updated rust custom mutator dependencies and LibAFL custom mutator - updated rust custom mutator dependencies and LibAFL custom mutator
- overall better sanitizer default setting handling
- several minor bugfixes - several minor bugfixes
### Version ++4.04c (release) ### Version ++4.04c (release)

View File

@ -98,6 +98,25 @@ ifeq "$(shell uname)" "Darwin"
OS:=macos OS:=macos
AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-deprecated-declarations AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-deprecated-declarations
GUM_ARCH:="" GUM_ARCH:=""
ifeq "$(ARCH)" "arm64"
TARGET_CC= \
"clang" \
"-target" \
"arm64-apple-macos10.9"
TARGET_CXX= \
"clang++" \
"-target" \
"arm64-apple-macos10.9"
else
TARGET_CC= \
"clang" \
"-target" \
"x86_64-apple-macos10.9"
TARGET_CXX= \
"clang++" \
"-target" \
"x86_64-apple-macos10.9"
endif
else else
ifdef DEBUG ifdef DEBUG
AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-prio-ctor-dtor AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-prio-ctor-dtor

View File

@ -43,6 +43,7 @@ u32 check_binary_signatures(u8 *fn);
void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin); void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin);
void print_suggested_envs(char *mispelled_env); void print_suggested_envs(char *mispelled_env);
void check_environment_vars(char **env); void check_environment_vars(char **env);
void set_sanitizer_defaults();
char **argv_cpy_dup(int argc, char **argv); char **argv_cpy_dup(int argc, char **argv);
void argv_cpy_free(char **argv); void argv_cpy_free(char **argv);

View File

@ -728,7 +728,11 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreateFunctionLocalArrayInSection(
Array->setSection(getSectionName(Section)); Array->setSection(getSectionName(Section));
#if (LLVM_VERSION_MAJOR >= 11) || \ #if (LLVM_VERSION_MAJOR >= 11) || \
(LLVM_VERSION_MAJOR == 10 && LLVM_VERSION_MINOR >= 1) (LLVM_VERSION_MAJOR == 10 && LLVM_VERSION_MINOR >= 1)
#if LLVM_VERSION_MAJOR >= 16
Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedValue()));
#else
Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize())); Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize()));
#endif
#else #else
Array->setAlignment(Align(4)); // cheating Array->setAlignment(Align(4)); // cheating
#endif #endif

View File

@ -149,6 +149,7 @@ u32 __afl_already_initialized_shm;
u32 __afl_already_initialized_forkserver; u32 __afl_already_initialized_forkserver;
u32 __afl_already_initialized_first; u32 __afl_already_initialized_first;
u32 __afl_already_initialized_second; u32 __afl_already_initialized_second;
u32 __afl_already_initialized_early;
u32 __afl_already_initialized_init; u32 __afl_already_initialized_init;
/* Dummy pipe for area_is_valid() */ /* Dummy pipe for area_is_valid() */
@ -1373,6 +1374,9 @@ __attribute__((constructor(EARLY_FS_PRIO))) void __early_forkserver(void) {
__attribute__((constructor(CTOR_PRIO))) void __afl_auto_early(void) { __attribute__((constructor(CTOR_PRIO))) void __afl_auto_early(void) {
if (__afl_already_initialized_early) return;
__afl_already_initialized_early = 1;
is_persistent = !!getenv(PERSIST_ENV_VAR); is_persistent = !!getenv(PERSIST_ENV_VAR);
if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return; if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
@ -1514,6 +1518,10 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
_is_sancov = 1; _is_sancov = 1;
__afl_auto_first();
__afl_auto_second();
__afl_auto_early();
if (__afl_debug) { if (__afl_debug) {
fprintf(stderr, fprintf(stderr,

View File

@ -12,6 +12,7 @@
#include <list> #include <list>
#include <string> #include <string>
#include <fstream> #include <fstream>
#include <cmath>
#include <llvm/Support/raw_ostream.h> #include <llvm/Support/raw_ostream.h>

View File

@ -8,6 +8,7 @@
#include <list> #include <list>
#include <string> #include <string>
#include <fstream> #include <fstream>
#include <optional>
#include <sys/time.h> #include <sys/time.h>
#include "llvm/Config/llvm-config.h" #include "llvm/Config/llvm-config.h"
@ -35,6 +36,12 @@ typedef long double max_align_t;
#if LLVM_VERSION_MAJOR >= 11 #if LLVM_VERSION_MAJOR >= 11
#define MNAME M.getSourceFileName() #define MNAME M.getSourceFileName()
#define FMNAME F.getParent()->getSourceFileName() #define FMNAME F.getParent()->getSourceFileName()
#if LLVM_VERSION_MAJOR >= 16
// None becomes deprecated
// the standard std::nullopt_t is recommended instead
// from C++17 and onwards.
constexpr std::nullopt_t None = std::nullopt;
#endif
#else #else
#define MNAME std::string("") #define MNAME std::string("")
#define FMNAME std::string("") #define FMNAME std::string("")

View File

@ -708,7 +708,11 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
/* since the call is the first instruction of the bb it is safe to /* since the call is the first instruction of the bb it is safe to
* replace it with a phi instruction */ * replace it with a phi instruction */
BasicBlock::iterator ii(callInst); BasicBlock::iterator ii(callInst);
#if LLVM_MAJOR >= 16
ReplaceInstWithInst(callInst->getParent(), ii, PN);
#else
ReplaceInstWithInst(callInst->getParent()->getInstList(), ii, PN); ReplaceInstWithInst(callInst->getParent()->getInstList(), ii, PN);
#endif
} }

View File

@ -322,8 +322,12 @@ bool SplitComparesTransform::simplifyFPCompares(Module &M) {
* block bb it is now at the position where the old FcmpInst was */ * block bb it is now at the position where the old FcmpInst was */
Instruction *fcmp_np; Instruction *fcmp_np;
fcmp_np = CmpInst::Create(Instruction::FCmp, new_pred, op0, op1); fcmp_np = CmpInst::Create(Instruction::FCmp, new_pred, op0, op1);
#if LLVM_MAJOR >= 16
fcmp_np->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
#else
bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
fcmp_np); fcmp_np);
#endif
/* create a new basic block which holds the new EQ fcmp */ /* create a new basic block which holds the new EQ fcmp */
Instruction *fcmp_eq; Instruction *fcmp_eq;
@ -331,7 +335,11 @@ bool SplitComparesTransform::simplifyFPCompares(Module &M) {
BasicBlock *middle_bb = BasicBlock *middle_bb =
BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb); BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb);
fcmp_eq = CmpInst::Create(Instruction::FCmp, CmpInst::FCMP_OEQ, op0, op1); fcmp_eq = CmpInst::Create(Instruction::FCmp, CmpInst::FCMP_OEQ, op0, op1);
#if LLVM_MAJOR >= 16
fcmp_eq->insertInto(middle_bb, middle_bb->end());
#else
middle_bb->getInstList().push_back(fcmp_eq); middle_bb->getInstList().push_back(fcmp_eq);
#endif
/* add an unconditional branch to the end of middle_bb with destination /* add an unconditional branch to the end of middle_bb with destination
* end_bb */ * end_bb */
BranchInst::Create(end_bb, middle_bb); BranchInst::Create(end_bb, middle_bb);
@ -352,7 +360,11 @@ bool SplitComparesTransform::simplifyFPCompares(Module &M) {
PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb); PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb);
/* replace the old FcmpInst with our new and shiny PHI inst */ /* replace the old FcmpInst with our new and shiny PHI inst */
BasicBlock::iterator ii(FcmpInst); BasicBlock::iterator ii(FcmpInst);
#if LLVM_MAJOR >= 16
ReplaceInstWithInst(FcmpInst->getParent(), ii, PN);
#else
ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN); ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN);
#endif
} }
@ -409,7 +421,11 @@ bool SplitComparesTransform::simplifyOrEqualsCompare(CmpInst *IcmpInst,
/* create the ICMP instruction with new_pred and add it to the old basic /* create the ICMP instruction with new_pred and add it to the old basic
* block bb it is now at the position where the old IcmpInst was */ * block bb it is now at the position where the old IcmpInst was */
CmpInst *icmp_np = CmpInst::Create(Instruction::ICmp, new_pred, op0, op1); CmpInst *icmp_np = CmpInst::Create(Instruction::ICmp, new_pred, op0, op1);
#if LLVM_MAJOR >= 16
icmp_np->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
#else
bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), icmp_np); bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), icmp_np);
#endif
/* create a new basic block which holds the new EQ icmp */ /* create a new basic block which holds the new EQ icmp */
CmpInst *icmp_eq; CmpInst *icmp_eq;
@ -417,7 +433,11 @@ bool SplitComparesTransform::simplifyOrEqualsCompare(CmpInst *IcmpInst,
BasicBlock *middle_bb = BasicBlock *middle_bb =
BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb); BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb);
icmp_eq = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, op0, op1); icmp_eq = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, op0, op1);
#if LLVM_MAJOR >= 16
icmp_eq->insertInto(middle_bb, middle_bb->end());
#else
middle_bb->getInstList().push_back(icmp_eq); middle_bb->getInstList().push_back(icmp_eq);
#endif
/* add an unconditional branch to the end of middle_bb with destination /* add an unconditional branch to the end of middle_bb with destination
* end_bb */ * end_bb */
BranchInst::Create(end_bb, middle_bb); BranchInst::Create(end_bb, middle_bb);
@ -438,7 +458,11 @@ bool SplitComparesTransform::simplifyOrEqualsCompare(CmpInst *IcmpInst,
PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb); PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb);
/* replace the old IcmpInst with our new and shiny PHI inst */ /* replace the old IcmpInst with our new and shiny PHI inst */
BasicBlock::iterator ii(IcmpInst); BasicBlock::iterator ii(IcmpInst);
#if LLVM_MAJOR >= 16
ReplaceInstWithInst(IcmpInst->getParent(), ii, PN);
#else
ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN); ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN);
#endif
worklist.push_back(icmp_np); worklist.push_back(icmp_np);
worklist.push_back(icmp_eq); worklist.push_back(icmp_eq);
@ -518,7 +542,11 @@ bool SplitComparesTransform::simplifySignedCompare(CmpInst *IcmpInst, Module &M,
} }
#if LLVM_MAJOR >= 16
icmp_inv_sig_cmp->insertInto(sign_bb, sign_bb->end());
#else
sign_bb->getInstList().push_back(icmp_inv_sig_cmp); sign_bb->getInstList().push_back(icmp_inv_sig_cmp);
#endif
BranchInst::Create(end_bb, sign_bb); BranchInst::Create(end_bb, sign_bb);
/* create a new bb which is executed if signedness is equal */ /* create a new bb which is executed if signedness is equal */
@ -528,7 +556,11 @@ bool SplitComparesTransform::simplifySignedCompare(CmpInst *IcmpInst, Module &M,
/* we can do a normal unsigned compare now */ /* we can do a normal unsigned compare now */
icmp_usign_cmp = CmpInst::Create(Instruction::ICmp, new_pred, op0, op1); icmp_usign_cmp = CmpInst::Create(Instruction::ICmp, new_pred, op0, op1);
#if LLVM_MAJOR >= 16
icmp_usign_cmp->insertInto(middle_bb, middle_bb->end());
#else
middle_bb->getInstList().push_back(icmp_usign_cmp); middle_bb->getInstList().push_back(icmp_usign_cmp);
#endif
BranchInst::Create(end_bb, middle_bb); BranchInst::Create(end_bb, middle_bb);
auto term = bb->getTerminator(); auto term = bb->getTerminator();
@ -543,7 +575,11 @@ bool SplitComparesTransform::simplifySignedCompare(CmpInst *IcmpInst, Module &M,
PN->addIncoming(icmp_inv_sig_cmp, sign_bb); PN->addIncoming(icmp_inv_sig_cmp, sign_bb);
BasicBlock::iterator ii(IcmpInst); BasicBlock::iterator ii(IcmpInst);
#if LLVM_MAJOR >= 16
ReplaceInstWithInst(IcmpInst->getParent(), ii, PN);
#else
ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN); ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN);
#endif
// save for later // save for later
worklist.push_back(icmp_usign_cmp); worklist.push_back(icmp_usign_cmp);
@ -717,7 +753,11 @@ bool SplitComparesTransform::splitCompare(CmpInst *cmp_inst, Module &M,
} }
#if LLVM_MAJOR >= 16
icmp_inv_cmp->insertInto(inv_cmp_bb, inv_cmp_bb->end());
#else
inv_cmp_bb->getInstList().push_back(icmp_inv_cmp); inv_cmp_bb->getInstList().push_back(icmp_inv_cmp);
#endif
worklist.push_back(icmp_inv_cmp); worklist.push_back(icmp_inv_cmp);
auto term = bb->getTerminator(); auto term = bb->getTerminator();
@ -728,12 +768,18 @@ bool SplitComparesTransform::splitCompare(CmpInst *cmp_inst, Module &M,
BasicBlock *cmp_low_bb = BasicBlock *cmp_low_bb =
BasicBlock::Create(C, "" /*"injected"*/, end_bb->getParent(), end_bb); BasicBlock::Create(C, "" /*"injected"*/, end_bb->getParent(), end_bb);
op0_low = new TruncInst(op0, NewIntType); op0_low = new TruncInst(op0, NewIntType);
cmp_low_bb->getInstList().push_back(op0_low);
op1_low = new TruncInst(op1, NewIntType); op1_low = new TruncInst(op1, NewIntType);
cmp_low_bb->getInstList().push_back(op1_low);
icmp_low = CmpInst::Create(Instruction::ICmp, pred, op0_low, op1_low); icmp_low = CmpInst::Create(Instruction::ICmp, pred, op0_low, op1_low);
#if LLVM_MAJOR >= 16
op0_low->insertInto(cmp_low_bb, cmp_low_bb->end());
op1_low->insertInto(cmp_low_bb, cmp_low_bb->end());
icmp_low->insertInto(cmp_low_bb, cmp_low_bb->end());
#else
cmp_low_bb->getInstList().push_back(op0_low);
cmp_low_bb->getInstList().push_back(op1_low);
cmp_low_bb->getInstList().push_back(icmp_low); cmp_low_bb->getInstList().push_back(icmp_low);
#endif
BranchInst::Create(end_bb, cmp_low_bb); BranchInst::Create(end_bb, cmp_low_bb);
BranchInst::Create(end_bb, cmp_low_bb, icmp_inv_cmp, inv_cmp_bb); BranchInst::Create(end_bb, cmp_low_bb, icmp_inv_cmp, inv_cmp_bb);
@ -754,7 +800,11 @@ bool SplitComparesTransform::splitCompare(CmpInst *cmp_inst, Module &M,
} }
BasicBlock::iterator ii(cmp_inst); BasicBlock::iterator ii(cmp_inst);
#if LLVM_MAJOR >= 16
ReplaceInstWithInst(cmp_inst->getParent(), ii, PN);
#else
ReplaceInstWithInst(cmp_inst->getParent()->getInstList(), ii, PN); ReplaceInstWithInst(cmp_inst->getParent()->getInstList(), ii, PN);
#endif
// We split the comparison into low and high. If this isn't our target // We split the comparison into low and high. If this isn't our target
// bitwidth we recursively split the low and high parts again until we have // bitwidth we recursively split the low and high parts again until we have
@ -999,13 +1049,21 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
Instruction *bpre_op0, *bpre_op1; Instruction *bpre_op0, *bpre_op1;
bpre_op0 = CastInst::Create(Instruction::BitCast, op0, bpre_op0 = CastInst::Create(Instruction::BitCast, op0,
IntegerType::get(C, op_size)); IntegerType::get(C, op_size));
#if LLVM_MAJOR >= 16
bpre_op0->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
#else
bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
bpre_op0); bpre_op0);
#endif
bpre_op1 = CastInst::Create(Instruction::BitCast, op1, bpre_op1 = CastInst::Create(Instruction::BitCast, op1,
IntegerType::get(C, op_size)); IntegerType::get(C, op_size));
#if LLVM_MAJOR >= 16
bpre_op1->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
#else
bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
bpre_op1); bpre_op1);
#endif
/* Check if any operand is NaN. /* Check if any operand is NaN.
* If so, all comparisons except unequal (which yields true) yield false */ * If so, all comparisons except unequal (which yields true) yield false */
@ -1025,34 +1083,42 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
Instruction *nan_op0, *nan_op1; Instruction *nan_op0, *nan_op1;
nan_op0 = BinaryOperator::Create(Instruction::Shl, bpre_op0, nan_op0 = BinaryOperator::Create(Instruction::Shl, bpre_op0,
ConstantInt::get(bpre_op0->getType(), 1)); ConstantInt::get(bpre_op0->getType(), 1));
bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
nan_op0);
/* compare to NaN interval */
Instruction *is_op0_nan =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, nan_op0,
ConstantInt::get(intType, NaN_lowend));
bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
is_op0_nan);
/* Check op1 for NaN */ /* Check op1 for NaN */
/* Shift right 1 Bit, ignore sign bit */ /* Shift right 1 Bit, ignore sign bit */
nan_op1 = BinaryOperator::Create(Instruction::Shl, bpre_op1, nan_op1 = BinaryOperator::Create(Instruction::Shl, bpre_op1,
ConstantInt::get(bpre_op1->getType(), 1)); ConstantInt::get(bpre_op1->getType(), 1));
bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), /* compare to NaN interval */
nan_op1); Instruction *is_op0_nan =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, nan_op0,
ConstantInt::get(intType, NaN_lowend));
/* compare to NaN interval */ /* compare to NaN interval */
Instruction *is_op1_nan = Instruction *is_op1_nan =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, nan_op1, CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, nan_op1,
ConstantInt::get(intType, NaN_lowend)); ConstantInt::get(intType, NaN_lowend));
bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
is_op1_nan);
/* combine checks */ /* combine checks */
Instruction *is_nan = Instruction *is_nan =
BinaryOperator::Create(Instruction::Or, is_op0_nan, is_op1_nan); BinaryOperator::Create(Instruction::Or, is_op0_nan, is_op1_nan);
#if LLVM_MAJOR >= 16
nan_op0->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
is_op0_nan->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
nan_op1->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
is_op1_nan->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
is_nan->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
#else
bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
nan_op0);
bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
is_op0_nan);
bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
nan_op1);
bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
is_op1_nan);
bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), is_nan); bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), is_nan);
#endif
/* the result of the comparison, when at least one op is NaN /* the result of the comparison, when at least one op is NaN
is true only for the "NOT EQUAL" predicates. */ is true only for the "NOT EQUAL" predicates. */
@ -1079,23 +1145,30 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
isMzero_op0 = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, bpre_op0, isMzero_op0 = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, bpre_op0,
ConstantInt::get(intType, MinusZero)); ConstantInt::get(intType, MinusZero));
isMzero_op1 = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, bpre_op1,
ConstantInt::get(intType, MinusZero));
b_op0 = SelectInst::Create(isMzero_op0, ConstantInt::get(intType, PlusZero),
bpre_op0);
b_op1 = SelectInst::Create(isMzero_op1, ConstantInt::get(intType, PlusZero),
bpre_op1);
#if LLVM_MAJOR >= 16
isMzero_op0->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
isMzero_op1->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
b_op0->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
b_op1->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
#else
nonan_bb->getInstList().insert( nonan_bb->getInstList().insert(
BasicBlock::iterator(nonan_bb->getTerminator()), isMzero_op0); BasicBlock::iterator(nonan_bb->getTerminator()), isMzero_op0);
isMzero_op1 = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, bpre_op1,
ConstantInt::get(intType, MinusZero));
nonan_bb->getInstList().insert( nonan_bb->getInstList().insert(
BasicBlock::iterator(nonan_bb->getTerminator()), isMzero_op1); BasicBlock::iterator(nonan_bb->getTerminator()), isMzero_op1);
b_op0 = SelectInst::Create(isMzero_op0, ConstantInt::get(intType, PlusZero),
bpre_op0);
nonan_bb->getInstList().insert( nonan_bb->getInstList().insert(
BasicBlock::iterator(nonan_bb->getTerminator()), b_op0); BasicBlock::iterator(nonan_bb->getTerminator()), b_op0);
b_op1 = SelectInst::Create(isMzero_op1, ConstantInt::get(intType, PlusZero),
bpre_op1);
nonan_bb->getInstList().insert( nonan_bb->getInstList().insert(
BasicBlock::iterator(nonan_bb->getTerminator()), b_op1); BasicBlock::iterator(nonan_bb->getTerminator()), b_op1);
#endif
/* isolate signs of value of floating point type */ /* isolate signs of value of floating point type */
@ -1106,26 +1179,34 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
s_s0 = s_s0 =
BinaryOperator::Create(Instruction::LShr, b_op0, BinaryOperator::Create(Instruction::LShr, b_op0,
ConstantInt::get(b_op0->getType(), op_size - 1)); ConstantInt::get(b_op0->getType(), op_size - 1));
nonan_bb->getInstList().insert(
BasicBlock::iterator(nonan_bb->getTerminator()), s_s0);
t_s0 = new TruncInst(s_s0, Int1Ty);
nonan_bb->getInstList().insert(
BasicBlock::iterator(nonan_bb->getTerminator()), t_s0);
s_s1 = s_s1 =
BinaryOperator::Create(Instruction::LShr, b_op1, BinaryOperator::Create(Instruction::LShr, b_op1,
ConstantInt::get(b_op1->getType(), op_size - 1)); ConstantInt::get(b_op1->getType(), op_size - 1));
nonan_bb->getInstList().insert( t_s0 = new TruncInst(s_s0, Int1Ty);
BasicBlock::iterator(nonan_bb->getTerminator()), s_s1);
t_s1 = new TruncInst(s_s1, Int1Ty); t_s1 = new TruncInst(s_s1, Int1Ty);
nonan_bb->getInstList().insert(
BasicBlock::iterator(nonan_bb->getTerminator()), t_s1);
/* compare of the sign bits */ /* compare of the sign bits */
icmp_sign_bit = icmp_sign_bit =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_s0, t_s1); CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_s0, t_s1);
#if LLVM_MAJOR >= 16
s_s0->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
t_s0->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
s_s1->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
t_s1->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
icmp_sign_bit->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
#else
nonan_bb->getInstList().insert(
BasicBlock::iterator(nonan_bb->getTerminator()), s_s0);
nonan_bb->getInstList().insert(
BasicBlock::iterator(nonan_bb->getTerminator()), t_s0);
nonan_bb->getInstList().insert(
BasicBlock::iterator(nonan_bb->getTerminator()), s_s1);
nonan_bb->getInstList().insert(
BasicBlock::iterator(nonan_bb->getTerminator()), t_s1);
nonan_bb->getInstList().insert( nonan_bb->getInstList().insert(
BasicBlock::iterator(nonan_bb->getTerminator()), icmp_sign_bit); BasicBlock::iterator(nonan_bb->getTerminator()), icmp_sign_bit);
#endif
/* create a new basic block which is executed if the signedness bits are /* create a new basic block which is executed if the signedness bits are
* equal */ * equal */
@ -1157,17 +1238,28 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
s_e1 = BinaryOperator::Create( s_e1 = BinaryOperator::Create(
Instruction::LShr, b_op1, Instruction::LShr, b_op1,
ConstantInt::get(b_op1->getType(), shiftR_exponent)); ConstantInt::get(b_op1->getType(), shiftR_exponent));
#if LLVM_MAJOR >= 16
s_e0->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator()));
s_e1->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator()));
#else
signequal_bb->getInstList().insert( signequal_bb->getInstList().insert(
BasicBlock::iterator(signequal_bb->getTerminator()), s_e0); BasicBlock::iterator(signequal_bb->getTerminator()), s_e0);
signequal_bb->getInstList().insert( signequal_bb->getInstList().insert(
BasicBlock::iterator(signequal_bb->getTerminator()), s_e1); BasicBlock::iterator(signequal_bb->getTerminator()), s_e1);
#endif
t_e0 = new TruncInst(s_e0, IntExponentTy); t_e0 = new TruncInst(s_e0, IntExponentTy);
t_e1 = new TruncInst(s_e1, IntExponentTy); t_e1 = new TruncInst(s_e1, IntExponentTy);
#if LLVM_MAJOR >= 16
t_e0->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator()));
t_e1->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator()));
#else
signequal_bb->getInstList().insert( signequal_bb->getInstList().insert(
BasicBlock::iterator(signequal_bb->getTerminator()), t_e0); BasicBlock::iterator(signequal_bb->getTerminator()), t_e0);
signequal_bb->getInstList().insert( signequal_bb->getInstList().insert(
BasicBlock::iterator(signequal_bb->getTerminator()), t_e1); BasicBlock::iterator(signequal_bb->getTerminator()), t_e1);
#endif
if (sizeInBits - precision < exTySizeBytes * 8) { if (sizeInBits - precision < exTySizeBytes * 8) {
@ -1177,10 +1269,15 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
m_e1 = BinaryOperator::Create( m_e1 = BinaryOperator::Create(
Instruction::And, t_e1, Instruction::And, t_e1,
ConstantInt::get(t_e1->getType(), mask_exponent)); ConstantInt::get(t_e1->getType(), mask_exponent));
#if LLVM_MAJOR >= 16
m_e0->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator()));
m_e1->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator()));
#else
signequal_bb->getInstList().insert( signequal_bb->getInstList().insert(
BasicBlock::iterator(signequal_bb->getTerminator()), m_e0); BasicBlock::iterator(signequal_bb->getTerminator()), m_e0);
signequal_bb->getInstList().insert( signequal_bb->getInstList().insert(
BasicBlock::iterator(signequal_bb->getTerminator()), m_e1); BasicBlock::iterator(signequal_bb->getTerminator()), m_e1);
#endif
} else { } else {
@ -1214,9 +1311,13 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
Instruction *icmp_exponent; Instruction *icmp_exponent;
icmp_exponents_equal = icmp_exponents_equal =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1); CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1);
#if LLVM_MAJOR >= 16
icmp_exponents_equal->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator()));
#else
signequal_bb->getInstList().insert( signequal_bb->getInstList().insert(
BasicBlock::iterator(signequal_bb->getTerminator()), BasicBlock::iterator(signequal_bb->getTerminator()),
icmp_exponents_equal); icmp_exponents_equal);
#endif
// shortcut for unequal exponents // shortcut for unequal exponents
signequal2_bb = signequal_bb->splitBasicBlock( signequal2_bb = signequal_bb->splitBasicBlock(
@ -1230,9 +1331,13 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
icmp_exponent = icmp_exponent =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, m_e0, m_e1); CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, m_e0, m_e1);
#if LLVM_MAJOR >= 16
icmp_exponent->insertInto(signequal2_bb, BasicBlock::iterator(signequal2_bb->getTerminator()));
#else
signequal2_bb->getInstList().insert( signequal2_bb->getInstList().insert(
BasicBlock::iterator(signequal2_bb->getTerminator()), BasicBlock::iterator(signequal2_bb->getTerminator()),
icmp_exponent); icmp_exponent);
#endif
icmp_exponent_result = icmp_exponent_result =
BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0); BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0);
break; break;
@ -1240,9 +1345,13 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
case CmpInst::FCMP_ULT: case CmpInst::FCMP_ULT:
icmp_exponents_equal = icmp_exponents_equal =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1); CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1);
#if LLVM_MAJOR >= 16
icmp_exponents_equal->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator()));
#else
signequal_bb->getInstList().insert( signequal_bb->getInstList().insert(
BasicBlock::iterator(signequal_bb->getTerminator()), BasicBlock::iterator(signequal_bb->getTerminator()),
icmp_exponents_equal); icmp_exponents_equal);
#endif
// shortcut for unequal exponents // shortcut for unequal exponents
signequal2_bb = signequal_bb->splitBasicBlock( signequal2_bb = signequal_bb->splitBasicBlock(
@ -1256,9 +1365,13 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
icmp_exponent = icmp_exponent =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, m_e0, m_e1); CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, m_e0, m_e1);
#if LLVM_MAJOR >= 16
icmp_exponent->insertInto(signequal2_bb, BasicBlock::iterator(signequal2_bb->getTerminator()));
#else
signequal2_bb->getInstList().insert( signequal2_bb->getInstList().insert(
BasicBlock::iterator(signequal2_bb->getTerminator()), BasicBlock::iterator(signequal2_bb->getTerminator()),
icmp_exponent); icmp_exponent);
#endif
icmp_exponent_result = icmp_exponent_result =
BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0); BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0);
break; break;
@ -1267,9 +1380,13 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
} }
#if LLVM_MAJOR >= 16
icmp_exponent_result->insertInto(signequal2_bb, BasicBlock::iterator(signequal2_bb->getTerminator()));
#else
signequal2_bb->getInstList().insert( signequal2_bb->getInstList().insert(
BasicBlock::iterator(signequal2_bb->getTerminator()), BasicBlock::iterator(signequal2_bb->getTerminator()),
icmp_exponent_result); icmp_exponent_result);
#endif
{ {
@ -1319,19 +1436,29 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
m_f1 = BinaryOperator::Create( m_f1 = BinaryOperator::Create(
Instruction::And, b_op1, Instruction::And, b_op1,
ConstantInt::get(b_op1->getType(), mask_fraction)); ConstantInt::get(b_op1->getType(), mask_fraction));
#if LLVM_MAJOR >= 16
m_f0->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator()));
m_f1->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator()));
#else
middle_bb->getInstList().insert( middle_bb->getInstList().insert(
BasicBlock::iterator(middle_bb->getTerminator()), m_f0); BasicBlock::iterator(middle_bb->getTerminator()), m_f0);
middle_bb->getInstList().insert( middle_bb->getInstList().insert(
BasicBlock::iterator(middle_bb->getTerminator()), m_f1); BasicBlock::iterator(middle_bb->getTerminator()), m_f1);
#endif
if (needTrunc) { if (needTrunc) {
t_f0 = new TruncInst(m_f0, IntFractionTy); t_f0 = new TruncInst(m_f0, IntFractionTy);
t_f1 = new TruncInst(m_f1, IntFractionTy); t_f1 = new TruncInst(m_f1, IntFractionTy);
#if LLVM_MAJOR >= 16
t_f0->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator()));
t_f1->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator()));
#else
middle_bb->getInstList().insert( middle_bb->getInstList().insert(
BasicBlock::iterator(middle_bb->getTerminator()), t_f0); BasicBlock::iterator(middle_bb->getTerminator()), t_f0);
middle_bb->getInstList().insert( middle_bb->getInstList().insert(
BasicBlock::iterator(middle_bb->getTerminator()), t_f1); BasicBlock::iterator(middle_bb->getTerminator()), t_f1);
#endif
} else { } else {
@ -1346,10 +1473,15 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
t_f0 = new TruncInst(b_op0, IntFractionTy); t_f0 = new TruncInst(b_op0, IntFractionTy);
t_f1 = new TruncInst(b_op1, IntFractionTy); t_f1 = new TruncInst(b_op1, IntFractionTy);
#if LLVM_MAJOR >= 16
t_f0->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator()));
t_f1->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator()));
#else
middle_bb->getInstList().insert( middle_bb->getInstList().insert(
BasicBlock::iterator(middle_bb->getTerminator()), t_f0); BasicBlock::iterator(middle_bb->getTerminator()), t_f0);
middle_bb->getInstList().insert( middle_bb->getInstList().insert(
BasicBlock::iterator(middle_bb->getTerminator()), t_f1); BasicBlock::iterator(middle_bb->getTerminator()), t_f1);
#endif
} else { } else {
@ -1370,18 +1502,26 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
case CmpInst::FCMP_OEQ: case CmpInst::FCMP_OEQ:
icmp_fraction_result = icmp_fraction_result =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_f0, t_f1); CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_f0, t_f1);
#if LLVM_MAJOR >= 16
icmp_fraction_result->insertInto(middle2_bb, BasicBlock::iterator(middle2_bb->getTerminator()));
#else
middle2_bb->getInstList().insert( middle2_bb->getInstList().insert(
BasicBlock::iterator(middle2_bb->getTerminator()), BasicBlock::iterator(middle2_bb->getTerminator()),
icmp_fraction_result); icmp_fraction_result);
#endif
break; break;
case CmpInst::FCMP_UNE: case CmpInst::FCMP_UNE:
case CmpInst::FCMP_ONE: case CmpInst::FCMP_ONE:
icmp_fraction_result = icmp_fraction_result =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_NE, t_f0, t_f1); CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_NE, t_f0, t_f1);
#if LLVM_MAJOR >= 16
icmp_fraction_result->insertInto(middle2_bb, BasicBlock::iterator(middle2_bb->getTerminator()));
#else
middle2_bb->getInstList().insert( middle2_bb->getInstList().insert(
BasicBlock::iterator(middle2_bb->getTerminator()), BasicBlock::iterator(middle2_bb->getTerminator()),
icmp_fraction_result); icmp_fraction_result);
#endif
break; break;
case CmpInst::FCMP_OGT: case CmpInst::FCMP_OGT:
@ -1402,21 +1542,31 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
if (FcmpInst->getPredicate() == CmpInst::FCMP_OGT || if (FcmpInst->getPredicate() == CmpInst::FCMP_OGT ||
FcmpInst->getPredicate() == CmpInst::FCMP_UGT) { FcmpInst->getPredicate() == CmpInst::FCMP_UGT) {
negative_bb->getInstList().push_back(
icmp_fraction_result = CmpInst::Create( icmp_fraction_result = CmpInst::Create(
Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1)); Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1);
positive_bb->getInstList().push_back(
icmp_fraction_result2 = CmpInst::Create( icmp_fraction_result2 = CmpInst::Create(
Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1)); Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1);
#if LLVM_MAJOR >= 16
icmp_fraction_result->insertInto(negative_bb, negative_bb->end());
icmp_fraction_result2->insertInto(positive_bb, negative_bb->end());
#else
negative_bb->getInstList().push_back(icmp_fraction_result);
positive_bb->getInstList().push_back(icmp_fraction_result2);
#endif
} else { } else {
negative_bb->getInstList().push_back(
icmp_fraction_result = CmpInst::Create( icmp_fraction_result = CmpInst::Create(
Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1)); Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1);
positive_bb->getInstList().push_back(
icmp_fraction_result2 = CmpInst::Create( icmp_fraction_result2 = CmpInst::Create(
Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1)); Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1);
#if LLVM_MAJOR >= 16
icmp_fraction_result->insertInto(negative_bb, negative_bb->end());
icmp_fraction_result2->insertInto(positive_bb, negative_bb->end());
#else
negative_bb->getInstList().push_back(icmp_fraction_result);
positive_bb->getInstList().push_back(icmp_fraction_result2);
#endif
} }
@ -1430,8 +1580,12 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
PN2 = PHINode::Create(Int1Ty, 2, ""); PN2 = PHINode::Create(Int1Ty, 2, "");
PN2->addIncoming(icmp_fraction_result, negative_bb); PN2->addIncoming(icmp_fraction_result, negative_bb);
PN2->addIncoming(icmp_fraction_result2, positive_bb); PN2->addIncoming(icmp_fraction_result2, positive_bb);
#if LLVM_MAJOR >= 16
PN2->insertInto(middle2_bb, BasicBlock::iterator(middle2_bb->getTerminator()));
#else
middle2_bb->getInstList().insert( middle2_bb->getInstList().insert(
BasicBlock::iterator(middle2_bb->getTerminator()), PN2); BasicBlock::iterator(middle2_bb->getTerminator()), PN2);
#endif
} break; } break;
@ -1494,7 +1648,11 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
} }
BasicBlock::iterator ii(FcmpInst); BasicBlock::iterator ii(FcmpInst);
#if LLVM_MAJOR >= 16
ReplaceInstWithInst(FcmpInst->getParent(), ii, PN);
#else
ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN); ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN);
#endif
++count; ++count;
} }

View File

@ -225,12 +225,20 @@ BasicBlock *SplitSwitchesTransform::switchConvert(
BasicBlock *NewNode = BasicBlock::Create(Val->getContext(), "NodeBlock", F); BasicBlock *NewNode = BasicBlock::Create(Val->getContext(), "NodeBlock", F);
Shift = BinaryOperator::Create(Instruction::LShr, Val, Shift = BinaryOperator::Create(Instruction::LShr, Val,
ConstantInt::get(ValType, smallestIndex * 8)); ConstantInt::get(ValType, smallestIndex * 8));
#if LLVM_VERSION_MAJOR >= 16
Shift->insertInto(NewNode, NewNode->end());
#else
NewNode->getInstList().push_back(Shift); NewNode->getInstList().push_back(Shift);
#endif
if (ValTypeBitWidth > 8) { if (ValTypeBitWidth > 8) {
Trunc = new TruncInst(Shift, ByteType); Trunc = new TruncInst(Shift, ByteType);
#if LLVM_VERSION_MAJOR >= 16
Trunc->insertInto(NewNode, NewNode->end());
#else
NewNode->getInstList().push_back(Trunc); NewNode->getInstList().push_back(Trunc);
#endif
} else { } else {
@ -253,7 +261,11 @@ BasicBlock *SplitSwitchesTransform::switchConvert(
ICmpInst *Comp = ICmpInst *Comp =
new ICmpInst(ICmpInst::ICMP_EQ, Trunc, ConstantInt::get(ByteType, byte), new ICmpInst(ICmpInst::ICMP_EQ, Trunc, ConstantInt::get(ByteType, byte),
"byteMatch"); "byteMatch");
#if LLVM_VERSION_MAJOR >= 16
Comp->insertInto(NewNode, NewNode->end());
#else
NewNode->getInstList().push_back(Comp); NewNode->getInstList().push_back(Comp);
#endif
bytesChecked[smallestIndex] = true; bytesChecked[smallestIndex] = true;
bool allBytesAreChecked = true; bool allBytesAreChecked = true;
@ -355,7 +367,11 @@ BasicBlock *SplitSwitchesTransform::switchConvert(
ICmpInst *Comp = ICmpInst *Comp =
new ICmpInst(ICmpInst::ICMP_ULT, Trunc, new ICmpInst(ICmpInst::ICMP_ULT, Trunc,
ConstantInt::get(ByteType, pivot), "byteMatch"); ConstantInt::get(ByteType, pivot), "byteMatch");
#if LLVM_VERSION_MAJOR >= 16
Comp->insertInto(NewNode, NewNode->end());
#else
NewNode->getInstList().push_back(Comp); NewNode->getInstList().push_back(Comp);
#endif
BranchInst::Create(LBB, RBB, Comp, NewNode); BranchInst::Create(LBB, RBB, Comp, NewNode);
} }
@ -452,7 +468,11 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) {
BranchInst::Create(SwitchBlock, OrigBlock); BranchInst::Create(SwitchBlock, OrigBlock);
/* We are now done with the switch instruction, delete it. */ /* We are now done with the switch instruction, delete it. */
#if LLVM_VERSION_MAJOR >= 16
SI->eraseFromParent();
#else
CurBlock->getInstList().erase(SI); CurBlock->getInstList().erase(SI);
#endif
/* we have to update the phi nodes! */ /* we have to update the phi nodes! */
for (BasicBlock::iterator I = Default->begin(); I != Default->end(); ++I) { for (BasicBlock::iterator I = Default->begin(); I != Default->end(); ++I) {

View File

@ -656,28 +656,6 @@ static void set_up_environment(char **argv) {
if (fsrv.out_fd < 0) { PFATAL("Unable to create '%s'", fsrv.out_file); } if (fsrv.out_fd < 0) { PFATAL("Unable to create '%s'", fsrv.out_file); }
/* Set sane defaults... */ /* Set sane defaults... */
x = get_afl_env("ASAN_OPTIONS");
if (x) {
if (!strstr(x, "abort_on_error=1")) {
FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!");
}
#ifndef ASAN_BUILD
if (!getenv("AFL_DEBUG") && !strstr(x, "symbolize=0")) {
FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!");
}
#endif
}
x = get_afl_env("MSAN_OPTIONS"); x = get_afl_env("MSAN_OPTIONS");
if (x) { if (x) {
@ -689,69 +667,9 @@ static void set_up_environment(char **argv) {
} }
if (!strstr(x, "symbolize=0")) {
FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!");
} }
} set_sanitizer_defaults();
x = get_afl_env("LSAN_OPTIONS");
if (x) {
if (!strstr(x, "symbolize=0")) {
FATAL("Custom LSAN_OPTIONS set without symbolize=0 - please fix!");
}
}
setenv("ASAN_OPTIONS",
"abort_on_error=1:"
"detect_leaks=0:"
"allocator_may_return_null=1:"
"detect_odr_violation=0:"
"symbolize=0:"
"handle_segv=0:"
"handle_sigbus=0:"
"handle_abort=0:"
"handle_sigfpe=0:"
"handle_sigill=0",
0);
setenv("UBSAN_OPTIONS",
"halt_on_error=1:"
"abort_on_error=1:"
"malloc_context_size=0:"
"allocator_may_return_null=1:"
"symbolize=0:"
"handle_segv=0:"
"handle_sigbus=0:"
"handle_abort=0:"
"handle_sigfpe=0:"
"handle_sigill=0",
0);
setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":"
"abort_on_error=1:"
"msan_track_origins=0"
"allocator_may_return_null=1:"
"symbolize=0:"
"handle_segv=0:"
"handle_sigbus=0:"
"handle_abort=0:"
"handle_sigfpe=0:"
"handle_sigill=0", 0);
setenv("LSAN_OPTIONS",
"exitcode=" STRINGIFY(LSAN_ERROR) ":"
"fast_unwind_on_malloc=0:"
"symbolize=0:"
"print_suppressions=0",
0);
if (get_afl_env("AFL_PRELOAD")) { if (get_afl_env("AFL_PRELOAD")) {

View File

@ -1050,6 +1050,12 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (getenv("AFL_USE_CFISAN")) { if (getenv("AFL_USE_CFISAN")) {
if (compiler_mode == GCC_PLUGIN || compiler_mode == GCC) {
cc_params[cc_par_cnt++] = "-fcf-protection=full";
} else {
if (!lto_mode) { if (!lto_mode) {
uint32_t i = 0, found = 0; uint32_t i = 0, found = 0;
@ -1064,6 +1070,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
} }
}
if (!getenv("AFL_DONT_OPTIMIZE")) { if (!getenv("AFL_DONT_OPTIMIZE")) {
cc_params[cc_par_cnt++] = "-g"; cc_params[cc_par_cnt++] = "-g";

View File

@ -58,6 +58,63 @@ u8 last_intr = 0;
#define AFL_PATH "/usr/local/lib/afl/" #define AFL_PATH "/usr/local/lib/afl/"
#endif #endif
void set_sanitizer_defaults() {
/* Set sane defaults for ASAN if nothing else is specified. */
u8 *have_asan_options = getenv("ASAN_OPTIONS");
u8 *have_ubsan_options = getenv("UBSAN_OPTIONS");
u8 *have_msan_options = getenv("MSAN_OPTIONS");
u8 *have_lsan_options = getenv("LSAN_OPTIONS");
u8 have_san_options = 0;
if (have_asan_options || have_ubsan_options || have_msan_options ||
have_lsan_options)
have_san_options = 1;
u8 default_options[1024] =
"detect_odr_violation=0:abort_on_error=1:symbolize=0:malloc_context_"
"size=0:allocator_may_return_null=1:handle_segv=0:handle_sigbus=0:"
"handle_abort=0:handle_sigfpe=0:handle_sigill=0:";
if (!have_lsan_options) strcat(default_options, "detect_leaks=0:");
/* Set sane defaults for ASAN if nothing else is specified. */
if (!have_san_options) setenv("ASAN_OPTIONS", default_options, 1);
/* Set sane defaults for UBSAN if nothing else is specified. */
if (!have_san_options) setenv("UBSAN_OPTIONS", default_options, 1);
/* MSAN is tricky, because it doesn't support abort_on_error=1 at this
point. So, we do this in a very hacky way. */
if (!have_msan_options) {
u8 buf[2048] = "";
if (!have_san_options) strcpy(buf, default_options);
strcat(buf, "exit_code=" STRINGIFY(MSAN_ERROR) ":msan_track_origins=0:");
setenv("MSAN_OPTIONS", buf, 1);
}
/* LSAN, too, does not support abort_on_error=1. (is this still true??) */
if (!have_lsan_options) {
u8 buf[2048] = "";
if (!have_san_options) strcpy(buf, default_options);
strcat(buf,
"exitcode=" STRINGIFY(
LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:");
setenv("LSAN_OPTIONS", buf, 1);
}
/* Envs for QASan */
setenv("QASAN_MAX_CALL_STACK", "0", 0);
setenv("QASAN_SYMBOLIZE", "0", 0);
}
u32 check_binary_signatures(u8 *fn) { u32 check_binary_signatures(u8 *fn) {
int ret = 0, fd = open(fn, O_RDONLY); int ret = 0, fd = open(fn, O_RDONLY);

View File

@ -688,70 +688,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 1); } if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 1); }
/* Set sane defaults for ASAN if nothing else is specified. */ /* Set sane defaults for sanitizers */
set_sanitizer_defaults();
if (!getenv("ASAN_OPTIONS"))
setenv("ASAN_OPTIONS",
"abort_on_error=1:"
"detect_leaks=0:"
"malloc_context_size=0:"
"symbolize=0:"
"allocator_may_return_null=1:"
"detect_odr_violation=0:"
"handle_segv=0:"
"handle_sigbus=0:"
"handle_abort=0:"
"handle_sigfpe=0:"
"handle_sigill=0",
1);
/* Set sane defaults for UBSAN if nothing else is specified. */
if (!getenv("UBSAN_OPTIONS"))
setenv("UBSAN_OPTIONS",
"halt_on_error=1:"
"abort_on_error=1:"
"malloc_context_size=0:"
"allocator_may_return_null=1:"
"symbolize=0:"
"handle_segv=0:"
"handle_sigbus=0:"
"handle_abort=0:"
"handle_sigfpe=0:"
"handle_sigill=0",
1);
/* Envs for QASan */
setenv("QASAN_MAX_CALL_STACK", "0", 0);
setenv("QASAN_SYMBOLIZE", "0", 0);
/* MSAN is tricky, because it doesn't support abort_on_error=1 at this
point. So, we do this in a very hacky way. */
if (!getenv("MSAN_OPTIONS"))
setenv("MSAN_OPTIONS",
"exit_code=" STRINGIFY(MSAN_ERROR) ":"
"symbolize=0:"
"abort_on_error=1:"
"malloc_context_size=0:"
"allocator_may_return_null=1:"
"msan_track_origins=0:"
"handle_segv=0:"
"handle_sigbus=0:"
"handle_abort=0:"
"handle_sigfpe=0:"
"handle_sigill=0",
1);
/* LSAN, too, does not support abort_on_error=1. */
if (!getenv("LSAN_OPTIONS"))
setenv("LSAN_OPTIONS",
"exitcode=" STRINGIFY(LSAN_ERROR) ":"
"fast_unwind_on_malloc=0:"
"symbolize=0:"
"print_suppressions=0",
1);
fsrv->init_child_func(fsrv, argv); fsrv->init_child_func(fsrv, argv);

View File

@ -1817,17 +1817,35 @@ static void handle_existing_out_dir(afl_state_t *afl) {
if (afl->file_extension) { if (afl->file_extension) {
fn = alloc_printf("%s/.cur_input.%s", afl->tmp_dir, afl->file_extension); fn = alloc_printf("%s/.cur_input.%s", afl->out_dir, afl->file_extension);
} else { } else {
fn = alloc_printf("%s/.cur_input", afl->tmp_dir); fn = alloc_printf("%s/.cur_input", afl->out_dir);
} }
if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; } if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
ck_free(fn); ck_free(fn);
if (afl->afl_env.afl_tmpdir) {
if (afl->file_extension) {
fn = alloc_printf("%s/.cur_input.%s", afl->afl_env.afl_tmpdir,
afl->file_extension);
} else {
fn = alloc_printf("%s/.cur_input", afl->afl_env.afl_tmpdir);
}
if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
ck_free(fn);
}
fn = alloc_printf("%s/fuzz_bitmap", afl->out_dir); fn = alloc_printf("%s/fuzz_bitmap", afl->out_dir);
if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; } if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
ck_free(fn); ck_free(fn);

View File

@ -311,7 +311,7 @@ static void usage(u8 *argv0, int more_help) {
"AFL_EARLY_FORKSERVER: force an early forkserver in an afl-clang-fast/\n" "AFL_EARLY_FORKSERVER: force an early forkserver in an afl-clang-fast/\n"
" afl-clang-lto/afl-gcc-fast target\n" " afl-clang-lto/afl-gcc-fast target\n"
"AFL_PERSISTENT: enforce persistent mode (if __AFL_LOOP is in a shared lib\n" "AFL_PERSISTENT: enforce persistent mode (if __AFL_LOOP is in a shared lib\n"
"AFL_DEFER_FORKSRV: enforced deferred forkserver (__AFL_INIT is in a .so\n" "AFL_DEFER_FORKSRV: enforced deferred forkserver (__AFL_INIT is in a .so)\n"
"\n" "\n"
); );
@ -2178,8 +2178,12 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->fsrv.out_file && afl->fsrv.use_shmem_fuzz) { if (afl->fsrv.out_file && afl->fsrv.use_shmem_fuzz) {
unlink(afl->fsrv.out_file);
afl->fsrv.out_file = NULL; afl->fsrv.out_file = NULL;
afl->fsrv.use_stdin = 0; afl->fsrv.use_stdin = 0;
close(afl->fsrv.out_fd);
afl->fsrv.out_fd = -1;
if (!afl->unicorn_mode && !afl->fsrv.use_stdin && !default_output) { if (!afl->unicorn_mode && !afl->fsrv.use_stdin && !default_output) {
WARNF( WARNF(

View File

@ -597,49 +597,8 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
char *afl_preload; char *afl_preload;
char *frida_afl_preload = NULL; char *frida_afl_preload = NULL;
setenv("ASAN_OPTIONS",
"abort_on_error=1:"
"detect_leaks=0:"
"allocator_may_return_null=1:"
"symbolize=0:"
"detect_odr_violation=0:"
"handle_segv=0:"
"handle_sigbus=0:"
"handle_abort=0:"
"handle_sigfpe=0:"
"handle_sigill=0",
0);
setenv("LSAN_OPTIONS", set_sanitizer_defaults();
"exitcode=" STRINGIFY(LSAN_ERROR) ":"
"fast_unwind_on_malloc=0:"
"symbolize=0:"
"print_suppressions=0",
0);
setenv("UBSAN_OPTIONS",
"halt_on_error=1:"
"abort_on_error=1:"
"malloc_context_size=0:"
"allocator_may_return_null=1:"
"symbolize=0:"
"handle_segv=0:"
"handle_sigbus=0:"
"handle_abort=0:"
"handle_sigfpe=0:"
"handle_sigill=0",
0);
setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":"
"abort_on_error=1:"
"msan_track_origins=0"
"allocator_may_return_null=1:"
"symbolize=0:"
"handle_segv=0:"
"handle_sigbus=0:"
"handle_abort=0:"
"handle_sigfpe=0:"
"handle_sigill=0", 0);
if (get_afl_env("AFL_PRELOAD")) { if (get_afl_env("AFL_PRELOAD")) {

View File

@ -674,27 +674,6 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
/* Set sane defaults... */ /* Set sane defaults... */
x = get_afl_env("ASAN_OPTIONS");
if (x) {
if (!strstr(x, "abort_on_error=1")) {
FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!");
}
#ifndef ASAN_BUILD
if (!getenv("AFL_DEBUG") && !strstr(x, "symbolize=0")) {
FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!");
}
#endif
}
x = get_afl_env("MSAN_OPTIONS"); x = get_afl_env("MSAN_OPTIONS");
if (x) { if (x) {
@ -706,69 +685,9 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
} }
if (!strstr(x, "symbolize=0")) {
FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!");
} }
} set_sanitizer_defaults();
x = get_afl_env("LSAN_OPTIONS");
if (x) {
if (!strstr(x, "symbolize=0")) {
FATAL("Custom LSAN_OPTIONS set without symbolize=0 - please fix!");
}
}
setenv("ASAN_OPTIONS",
"abort_on_error=1:"
"detect_leaks=0:"
"allocator_may_return_null=1:"
"symbolize=0:"
"detect_odr_violation=0:"
"handle_segv=0:"
"handle_sigbus=0:"
"handle_abort=0:"
"handle_sigfpe=0:"
"handle_sigill=0",
0);
setenv("UBSAN_OPTIONS",
"halt_on_error=1:"
"abort_on_error=1:"
"malloc_context_size=0:"
"allocator_may_return_null=1:"
"symbolize=0:"
"handle_segv=0:"
"handle_sigbus=0:"
"handle_abort=0:"
"handle_sigfpe=0:"
"handle_sigill=0",
0);
setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":"
"abort_on_error=1:"
"msan_track_origins=0"
"allocator_may_return_null=1:"
"symbolize=0:"
"handle_segv=0:"
"handle_sigbus=0:"
"handle_abort=0:"
"handle_sigfpe=0:"
"handle_sigill=0", 0);
setenv("LSAN_OPTIONS",
"exitcode=" STRINGIFY(LSAN_ERROR) ":"
"fast_unwind_on_malloc=0:"
"symbolize=0:"
"print_suppressions=0",
0);
if (get_afl_env("AFL_PRELOAD")) { if (get_afl_env("AFL_PRELOAD")) {

View File

@ -1 +1 @@
2df75f3e f2cede37

View File

@ -121,17 +121,19 @@ PIP_FOUND=0
for PYTHON in $PYTHONS ; do for PYTHON in $PYTHONS ; do
if $PYTHON -c "import pip" ; then if $PYTHON -c "import pip" ; then
if $PYTHON -c "import wheel" ; then
PIP_FOUND=1 PIP_FOUND=1
PYTHONBIN=$PYTHON PYTHONBIN=$PYTHON
break break
fi fi
fi
done done
if [ "0" = $PIP_FOUND ]; then if [ "0" = $PIP_FOUND ]; then
echo "[-] Error: Python pip not found. Run 'sudo apt-get install python-pip', or install python3-pip, or run '$PYTHONBIN -m ensurepip', or create a virtualenv, or ..." echo "[-] Error: Python pip or python wheel not found. Run 'sudo apt-get install python3-pip', or run '$PYTHONBIN -m ensurepip', or create a virtualenv, or ... - and 'pip3 install wheel'"
PREREQ_NOTFOUND=1 PREREQ_NOTFOUND=1
fi fi

View File

@ -194,7 +194,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
} }
if (!strstr(x, "symbolize=0")) { if (!getenv("AFL_DEBUG") && !strstr(x, "symbolize=0")) {
FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!"); FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!");
@ -213,7 +213,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
} }
if (!strstr(x, "symbolize=0")) { if (!getenv("AFL_DEBUG") && !strstr(x, "symbolize=0")) {
FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!"); FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!");
@ -221,18 +221,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
} }
setenv("ASAN_OPTIONS", set_sanitizer_defaults();
"abort_on_error=1:"
"detect_leaks=0:"
"symbolize=0:"
"allocator_may_return_null=1",
0);
setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":"
"symbolize=0:"
"abort_on_error=1:"
"allocator_may_return_null=1:"
"msan_track_origins=0", 0);
if (get_afl_env("AFL_PRELOAD")) { if (get_afl_env("AFL_PRELOAD")) {