• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 laf-intel
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 
21 #include <list>
22 #include <string>
23 #include <fstream>
24 #include <sys/time.h>
25 #include "llvm/Config/llvm-config.h"
26 
27 #include "llvm/ADT/Statistic.h"
28 #include "llvm/IR/IRBuilder.h"
29 #if LLVM_MAJOR >= 11                                /* use new pass manager */
30   #include "llvm/Passes/PassPlugin.h"
31   #include "llvm/Passes/PassBuilder.h"
32   #include "llvm/IR/PassManager.h"
33 #else
34   #include "llvm/IR/LegacyPassManager.h"
35   #include "llvm/Transforms/IPO/PassManagerBuilder.h"
36 #endif
37 #include "llvm/IR/Module.h"
38 #include "llvm/Support/Debug.h"
39 #include "llvm/Support/raw_ostream.h"
40 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
41 #include "llvm/Pass.h"
42 #include "llvm/Analysis/ValueTracking.h"
43 #if LLVM_VERSION_MAJOR >= 14                /* how about stable interfaces? */
44   #include "llvm/Passes/OptimizationLevel.h"
45 #endif
46 
47 #if LLVM_VERSION_MAJOR >= 4 || \
48     (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
49   #include "llvm/IR/Verifier.h"
50   #include "llvm/IR/DebugInfo.h"
51 #else
52   #include "llvm/Analysis/Verifier.h"
53   #include "llvm/DebugInfo.h"
54   #define nullptr 0
55 #endif
56 
57 #include <set>
58 #include "afl-llvm-common.h"
59 
60 using namespace llvm;
61 
62 namespace {
63 
64 #if LLVM_MAJOR >= 11                                /* use new pass manager */
65 class CompareTransform : public PassInfoMixin<CompareTransform> {
66 
67  public:
CompareTransform()68   CompareTransform() {
69 
70 #else
71 class CompareTransform : public ModulePass {
72 
73  public:
74   static char ID;
75   CompareTransform() : ModulePass(ID) {
76 
77 #endif
78 
79     initInstrumentList();
80 
81   }
82 
83 #if LLVM_MAJOR < 11
84   #if LLVM_VERSION_MAJOR >= 4
85   StringRef getPassName() const override {
86 
87   #else
88   const char *getPassName() const override {
89 
90   #endif
91 
92     return "cmplog transform";
93 
94   }
95 
96 #endif
97 
98 #if LLVM_MAJOR >= 11                                /* use new pass manager */
99   PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
100 #else
101   bool runOnModule(Module &M) override;
102 #endif
103 
104  private:
105   bool transformCmps(Module &M, const bool processStrcmp,
106                      const bool processMemcmp, const bool processStrncmp,
107                      const bool processStrcasecmp,
108                      const bool processStrncasecmp);
109 
110 };
111 
112 }  // namespace
113 
114 #if LLVM_MAJOR >= 11                                /* use new pass manager */
115 extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
116 llvmGetPassPluginInfo() {
117 
118   return {LLVM_PLUGIN_API_VERSION, "comparetransform", "v0.1",
119           /* lambda to insert our pass into the pass pipeline. */
120           [](PassBuilder &PB) {
121 
122   #if 1
123     #if LLVM_VERSION_MAJOR <= 13
124             using OptimizationLevel = typename PassBuilder::OptimizationLevel;
125     #endif
126             PB.registerOptimizerLastEPCallback(
127                 [](ModulePassManager &MPM, OptimizationLevel OL) {
128 
129                   MPM.addPass(CompareTransform());
130 
131                 });
132 
133   /* TODO LTO registration */
134   #else
135             using PipelineElement = typename PassBuilder::PipelineElement;
136             PB.registerPipelineParsingCallback([](StringRef          Name,
137                                                   ModulePassManager &MPM,
138                                                   ArrayRef<PipelineElement>) {
139 
140               if (Name == "comparetransform") {
141 
142                 MPM.addPass(CompareTransform());
143                 return true;
144 
145               } else {
146 
147                 return false;
148 
149               }
150 
151             });
152 
153   #endif
154 
155           }};
156 
157 }
158 
159 #else
160 char CompareTransform::ID = 0;
161 #endif
162 
163 bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
164                                      const bool processMemcmp,
165                                      const bool processStrncmp,
166                                      const bool processStrcasecmp,
167                                      const bool processStrncasecmp) {
168 
169   DenseMap<Value *, std::string *> valueMap;
170   std::vector<CallInst *>          calls;
171   LLVMContext &                    C = M.getContext();
172   IntegerType *                    Int8Ty = IntegerType::getInt8Ty(C);
173   IntegerType *                    Int32Ty = IntegerType::getInt32Ty(C);
174   IntegerType *                    Int64Ty = IntegerType::getInt64Ty(C);
175 
176 #if LLVM_VERSION_MAJOR >= 9
177   FunctionCallee tolowerFn;
178 #else
179   Function *tolowerFn;
180 #endif
181   {
182 
183 #if LLVM_VERSION_MAJOR >= 9
184     FunctionCallee
185 #else
186     Constant *
187 #endif
188         c = M.getOrInsertFunction("tolower", Int32Ty, Int32Ty
189 #if LLVM_VERSION_MAJOR < 5
190                                   ,
191                                   NULL
192 #endif
193         );
194 #if LLVM_VERSION_MAJOR >= 9
195     tolowerFn = c;
196 #else
197     tolowerFn = cast<Function>(c);
198 #endif
199 
200   }
201 
202   /* iterate over all functions, bbs and instruction and add suitable calls to
203    * strcmp/memcmp/strncmp/strcasecmp/strncasecmp */
204   for (auto &F : M) {
205 
206     if (!isInInstrumentList(&F, MNAME)) continue;
207 
208     for (auto &BB : F) {
209 
210       for (auto &IN : BB) {
211 
212         CallInst *callInst = nullptr;
213 
214         if ((callInst = dyn_cast<CallInst>(&IN))) {
215 
216           bool isStrcmp = processStrcmp;
217           bool isMemcmp = processMemcmp;
218           bool isStrncmp = processStrncmp;
219           bool isStrcasecmp = processStrcasecmp;
220           bool isStrncasecmp = processStrncasecmp;
221           bool isIntMemcpy = true;
222 
223           Function *Callee = callInst->getCalledFunction();
224           if (!Callee) continue;
225           if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
226           StringRef FuncName = Callee->getName();
227           isStrcmp &=
228               (!FuncName.compare("strcmp") || !FuncName.compare("xmlStrcmp") ||
229                !FuncName.compare("xmlStrEqual") ||
230                !FuncName.compare("g_strcmp0") ||
231                !FuncName.compare("curl_strequal") ||
232                !FuncName.compare("strcsequal"));
233           isMemcmp &=
234               (!FuncName.compare("memcmp") || !FuncName.compare("bcmp") ||
235                !FuncName.compare("CRYPTO_memcmp") ||
236                !FuncName.compare("OPENSSL_memcmp") ||
237                !FuncName.compare("memcmp_const_time") ||
238                !FuncName.compare("memcmpct"));
239           isStrncmp &= (!FuncName.compare("strncmp") ||
240                         !FuncName.compare("xmlStrncmp") ||
241                         !FuncName.compare("curl_strnequal"));
242           isStrcasecmp &= (!FuncName.compare("strcasecmp") ||
243                            !FuncName.compare("stricmp") ||
244                            !FuncName.compare("ap_cstr_casecmp") ||
245                            !FuncName.compare("OPENSSL_strcasecmp") ||
246                            !FuncName.compare("xmlStrcasecmp") ||
247                            !FuncName.compare("g_strcasecmp") ||
248                            !FuncName.compare("g_ascii_strcasecmp") ||
249                            !FuncName.compare("Curl_strcasecompare") ||
250                            !FuncName.compare("Curl_safe_strcasecompare") ||
251                            !FuncName.compare("cmsstrcasecmp"));
252           isStrncasecmp &= (!FuncName.compare("strncasecmp") ||
253                             !FuncName.compare("strnicmp") ||
254                             !FuncName.compare("ap_cstr_casecmpn") ||
255                             !FuncName.compare("OPENSSL_strncasecmp") ||
256                             !FuncName.compare("xmlStrncasecmp") ||
257                             !FuncName.compare("g_ascii_strncasecmp") ||
258                             !FuncName.compare("Curl_strncasecompare") ||
259                             !FuncName.compare("g_strncasecmp"));
260           isIntMemcpy &= !FuncName.compare("llvm.memcpy.p0i8.p0i8.i64");
261 
262           if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
263               !isStrncasecmp && !isIntMemcpy)
264             continue;
265 
266           /* Verify the strcmp/memcmp/strncmp/strcasecmp/strncasecmp function
267            * prototype */
268           FunctionType *FT = Callee->getFunctionType();
269 
270           isStrcmp &=
271               FT->getNumParams() == 2 && FT->getReturnType()->isIntegerTy(32) &&
272               FT->getParamType(0) == FT->getParamType(1) &&
273               FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext());
274           isStrcasecmp &=
275               FT->getNumParams() == 2 && FT->getReturnType()->isIntegerTy(32) &&
276               FT->getParamType(0) == FT->getParamType(1) &&
277               FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext());
278           isMemcmp &= FT->getNumParams() == 3 &&
279                       FT->getReturnType()->isIntegerTy(32) &&
280                       FT->getParamType(0)->isPointerTy() &&
281                       FT->getParamType(1)->isPointerTy() &&
282                       FT->getParamType(2)->isIntegerTy();
283           isStrncmp &= FT->getNumParams() == 3 &&
284                        FT->getReturnType()->isIntegerTy(32) &&
285                        FT->getParamType(0) == FT->getParamType(1) &&
286                        FT->getParamType(0) ==
287                            IntegerType::getInt8PtrTy(M.getContext()) &&
288                        FT->getParamType(2)->isIntegerTy();
289           isStrncasecmp &= FT->getNumParams() == 3 &&
290                            FT->getReturnType()->isIntegerTy(32) &&
291                            FT->getParamType(0) == FT->getParamType(1) &&
292                            FT->getParamType(0) ==
293                                IntegerType::getInt8PtrTy(M.getContext()) &&
294                            FT->getParamType(2)->isIntegerTy();
295 
296           if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
297               !isStrncasecmp && !isIntMemcpy)
298             continue;
299 
300           /* is a str{n,}{case,}cmp/memcmp, check if we have
301            * str{case,}cmp(x, "const") or str{case,}cmp("const", x)
302            * strn{case,}cmp(x, "const", ..) or strn{case,}cmp("const", x, ..)
303            * memcmp(x, "const", ..) or memcmp("const", x, ..) */
304           Value *Str1P = callInst->getArgOperand(0),
305                 *Str2P = callInst->getArgOperand(1);
306           StringRef Str1, Str2;
307           bool      HasStr1 = getConstantStringInfo(Str1P, Str1);
308           bool      HasStr2 = getConstantStringInfo(Str2P, Str2);
309 
310           if (isIntMemcpy && HasStr2) {
311 
312             valueMap[Str1P] = new std::string(Str2.str());
313             // fprintf(stderr, "saved %s for %p\n", Str2.str().c_str(), Str1P);
314             continue;
315 
316           }
317 
318           // not literal? maybe global or local variable
319           if (!(HasStr1 || HasStr2)) {
320 
321             auto *Ptr = dyn_cast<ConstantExpr>(Str2P);
322             if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) {
323 
324               if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
325 
326                 if (Var->hasInitializer()) {
327 
328                   if (auto *Array =
329                           dyn_cast<ConstantDataArray>(Var->getInitializer())) {
330 
331                     HasStr2 = true;
332                     Str2 = Array->getRawDataValues();
333                     valueMap[Str2P] = new std::string(Str2.str());
334                     // fprintf(stderr, "glo2 %s\n", Str2.str().c_str());
335 
336                   }
337 
338                 }
339 
340               }
341 
342             }
343 
344             if (!HasStr2) {
345 
346               Ptr = dyn_cast<ConstantExpr>(Str1P);
347               if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) {
348 
349                 if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
350 
351                   if (Var->hasInitializer()) {
352 
353                     if (auto *Array = dyn_cast<ConstantDataArray>(
354                             Var->getInitializer())) {
355 
356                       HasStr1 = true;
357                       Str1 = Array->getRawDataValues();
358                       valueMap[Str1P] = new std::string(Str1.str());
359                       // fprintf(stderr, "glo1 %s\n", Str1.str().c_str());
360 
361                     }
362 
363                   }
364 
365                 }
366 
367               }
368 
369             } else if (isIntMemcpy) {
370 
371               valueMap[Str1P] = new std::string(Str2.str());
372               // fprintf(stderr, "saved\n");
373 
374             }
375 
376           }
377 
378           if (isIntMemcpy) continue;
379 
380           if (!(HasStr1 || HasStr2)) {
381 
382             // do we have a saved local variable initialization?
383             std::string *val = valueMap[Str1P];
384             if (val && !val->empty()) {
385 
386               Str1 = StringRef(*val);
387               HasStr1 = true;
388               // fprintf(stderr, "loaded1 %s\n", Str1.str().c_str());
389 
390             } else {
391 
392               val = valueMap[Str2P];
393               if (val && !val->empty()) {
394 
395                 Str2 = StringRef(*val);
396                 HasStr2 = true;
397                 // fprintf(stderr, "loaded2 %s\n", Str2.str().c_str());
398 
399               }
400 
401             }
402 
403           }
404 
405           /* handle cases of one string is const, one string is variable */
406           if (!(HasStr1 || HasStr2)) continue;
407 
408           if (isMemcmp || isStrncmp || isStrncasecmp) {
409 
410             /* check if third operand is a constant integer
411              * strlen("constStr") and sizeof() are treated as constant */
412             Value *      op2 = callInst->getArgOperand(2);
413             ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
414             if (ilen) {
415 
416               // if len is zero this is a pointless call but allow real
417               // implementation to worry about that
418               if (ilen->getZExtValue() < 2) { continue; }
419 
420             } else if (isMemcmp) {
421 
422               // this *may* supply a len greater than the constant string at
423               // runtime so similarly we don't want to have to handle that
424               continue;
425 
426             }
427 
428           }
429 
430           calls.push_back(callInst);
431 
432         }
433 
434       }
435 
436     }
437 
438   }
439 
440   if (!calls.size()) return false;
441   if (!be_quiet)
442     printf(
443         "Replacing %zu calls to strcmp/memcmp/strncmp/strcasecmp/strncasecmp\n",
444         calls.size());
445 
446   for (auto &callInst : calls) {
447 
448     Value *Str1P = callInst->getArgOperand(0),
449           *Str2P = callInst->getArgOperand(1);
450     StringRef   Str1, Str2, ConstStr;
451     std::string TmpConstStr;
452     Value *     VarStr;
453     bool        HasStr1 = getConstantStringInfo(Str1P, Str1);
454     bool        HasStr2 = getConstantStringInfo(Str2P, Str2);
455     uint64_t    constStrLen, unrollLen, constSizedLen = 0;
456     bool        isMemcmp = false;
457     bool        isSizedcmp = false;
458     bool        isCaseInsensitive = false;
459     bool        needs_null = false;
460     Function *  Callee = callInst->getCalledFunction();
461 
462     if (Callee) {
463 
464       if (!Callee->getName().compare("memcmp") ||
465           !Callee->getName().compare("bcmp") ||
466           !Callee->getName().compare("CRYPTO_memcmp") ||
467           !Callee->getName().compare("OPENSSL_memcmp") ||
468           !Callee->getName().compare("memcmp_const_time") ||
469           !Callee->getName().compare("memcmpct") ||
470           !Callee->getName().compare("llvm.memcpy.p0i8.p0i8.i64"))
471         isMemcmp = true;
472 
473       if (isMemcmp || !Callee->getName().compare("strncmp") ||
474           !Callee->getName().compare("xmlStrncmp") ||
475           !Callee->getName().compare("curl_strnequal") ||
476           !Callee->getName().compare("strncasecmp") ||
477           !Callee->getName().compare("strnicmp") ||
478           !Callee->getName().compare("ap_cstr_casecmpn") ||
479           !Callee->getName().compare("OPENSSL_strncasecmp") ||
480           !Callee->getName().compare("xmlStrncasecmp") ||
481           !Callee->getName().compare("g_ascii_strncasecmp") ||
482           !Callee->getName().compare("Curl_strncasecompare") ||
483           !Callee->getName().compare("g_strncasecmp"))
484         isSizedcmp = true;
485 
486       if (!Callee->getName().compare("strcasecmp") ||
487           !Callee->getName().compare("stricmp") ||
488           !Callee->getName().compare("ap_cstr_casecmp") ||
489           !Callee->getName().compare("OPENSSL_strcasecmp") ||
490           !Callee->getName().compare("xmlStrcasecmp") ||
491           !Callee->getName().compare("g_strcasecmp") ||
492           !Callee->getName().compare("g_ascii_strcasecmp") ||
493           !Callee->getName().compare("Curl_strcasecompare") ||
494           !Callee->getName().compare("Curl_safe_strcasecompare") ||
495           !Callee->getName().compare("cmsstrcasecmp") ||
496           !Callee->getName().compare("strncasecmp") ||
497           !Callee->getName().compare("strnicmp") ||
498           !Callee->getName().compare("ap_cstr_casecmpn") ||
499           !Callee->getName().compare("OPENSSL_strncasecmp") ||
500           !Callee->getName().compare("xmlStrncasecmp") ||
501           !Callee->getName().compare("g_ascii_strncasecmp") ||
502           !Callee->getName().compare("Curl_strncasecompare") ||
503           !Callee->getName().compare("g_strncasecmp"))
504         isCaseInsensitive = true;
505 
506     }
507 
508     if (!isSizedcmp) needs_null = true;
509 
510     Value *sizedValue = isSizedcmp ? callInst->getArgOperand(2) : NULL;
511     bool   isConstSized = sizedValue && isa<ConstantInt>(sizedValue);
512 
513     if (!(HasStr1 || HasStr2)) {
514 
515       // do we have a saved local or global variable initialization?
516       std::string *val = valueMap[Str1P];
517       if (val && !val->empty()) {
518 
519         Str1 = StringRef(*val);
520         HasStr1 = true;
521 
522       } else {
523 
524         val = valueMap[Str2P];
525         if (val && !val->empty()) {
526 
527           Str2 = StringRef(*val);
528           // HasStr2 = true;
529 
530         }
531 
532       }
533 
534     }
535 
536     if (isConstSized) {
537 
538       constSizedLen = dyn_cast<ConstantInt>(sizedValue)->getZExtValue();
539 
540     }
541 
542     if (HasStr1) {
543 
544       TmpConstStr = Str1.str();
545       VarStr = Str2P;
546 
547     } else {
548 
549       TmpConstStr = Str2.str();
550       VarStr = Str1P;
551 
552     }
553 
554     if (TmpConstStr.length() < 2 ||
555         (TmpConstStr.length() == 2 && TmpConstStr[1] == 0)) {
556 
557       continue;
558 
559     }
560 
561     // the following is in general OK, but strncmp is sometimes used in binary
562     // data structures and this can result in crashes :( so it is commented out
563 
564     // add null termination character implicit in c strings
565     if (needs_null && TmpConstStr[TmpConstStr.length() - 1] != 0) {
566 
567       TmpConstStr.append("\0", 1);
568 
569     }
570 
571     // in the unusual case the const str has embedded null
572     // characters, the string comparison functions should terminate
573     // at the first null
574     if (!isMemcmp && TmpConstStr.find('\0') != std::string::npos) {
575 
576       TmpConstStr.assign(TmpConstStr, 0, TmpConstStr.find('\0') + 1);
577 
578     }
579 
580     constStrLen = TmpConstStr.length();
581     // prefer use of StringRef (in comparison to std::string a StringRef has
582     // built-in runtime bounds checking, which makes debugging easier)
583     ConstStr = StringRef(TmpConstStr);
584 
585     if (isConstSized)
586       unrollLen = constSizedLen < constStrLen ? constSizedLen : constStrLen;
587     else
588       unrollLen = constStrLen;
589 
590     /* split before the call instruction */
591     BasicBlock *bb = callInst->getParent();
592     BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(callInst));
593 
594     BasicBlock *next_lenchk_bb = NULL;
595     if (isSizedcmp && !isConstSized) {
596 
597       next_lenchk_bb =
598           BasicBlock::Create(C, "len_check", end_bb->getParent(), end_bb);
599       BranchInst::Create(end_bb, next_lenchk_bb);
600 
601     }
602 
603     BasicBlock *next_cmp_bb =
604         BasicBlock::Create(C, "cmp_added", end_bb->getParent(), end_bb);
605     BranchInst::Create(end_bb, next_cmp_bb);
606     PHINode *PN = PHINode::Create(
607         Int32Ty, (next_lenchk_bb ? 2 : 1) * unrollLen + 1, "cmp_phi");
608 
609 #if LLVM_VERSION_MAJOR >= 8
610     Instruction *term = bb->getTerminator();
611 #else
612     TerminatorInst *term = bb->getTerminator();
613 #endif
614     BranchInst::Create(next_lenchk_bb ? next_lenchk_bb : next_cmp_bb, bb);
615     term->eraseFromParent();
616 
617     for (uint64_t i = 0; i < unrollLen; i++) {
618 
619       BasicBlock *  cur_cmp_bb = next_cmp_bb, *cur_lenchk_bb = next_lenchk_bb;
620       unsigned char c;
621 
622       if (cur_lenchk_bb) {
623 
624         IRBuilder<> cur_lenchk_IRB(&*(cur_lenchk_bb->getFirstInsertionPt()));
625         Value *     icmp = cur_lenchk_IRB.CreateICmpEQ(
626             sizedValue, ConstantInt::get(sizedValue->getType(), i));
627         cur_lenchk_IRB.CreateCondBr(icmp, end_bb, cur_cmp_bb);
628         cur_lenchk_bb->getTerminator()->eraseFromParent();
629 
630         PN->addIncoming(ConstantInt::get(Int32Ty, 0), cur_lenchk_bb);
631 
632       }
633 
634       if (isCaseInsensitive)
635         c = (unsigned char)(tolower((int)ConstStr[i]) & 0xff);
636       else
637         c = (unsigned char)ConstStr[i];
638 
639       IRBuilder<> cur_cmp_IRB(&*(cur_cmp_bb->getFirstInsertionPt()));
640 
641       Value *v = ConstantInt::get(Int64Ty, i);
642       Value *ele = cur_cmp_IRB.CreateInBoundsGEP(
643 #if LLVM_VERSION_MAJOR >= 14
644           Int8Ty,
645 #endif
646           VarStr, v, "empty");
647       Value *load = cur_cmp_IRB.CreateLoad(
648 #if LLVM_VERSION_MAJOR >= 14
649           Int8Ty,
650 #endif
651           ele);
652 
653       if (isCaseInsensitive) {
654 
655         // load >= 'A' && load <= 'Z' ? load | 0x020 : load
656         load = cur_cmp_IRB.CreateZExt(load, Int32Ty);
657         std::vector<Value *> args;
658         args.push_back(load);
659         load = cur_cmp_IRB.CreateCall(tolowerFn, args);
660         load = cur_cmp_IRB.CreateTrunc(load, Int8Ty);
661 
662       }
663 
664       Value *isub;
665       if (HasStr1)
666         isub = cur_cmp_IRB.CreateSub(ConstantInt::get(Int8Ty, c), load);
667       else
668         isub = cur_cmp_IRB.CreateSub(load, ConstantInt::get(Int8Ty, c));
669 
670       Value *sext = cur_cmp_IRB.CreateSExt(isub, Int32Ty);
671       PN->addIncoming(sext, cur_cmp_bb);
672 
673       if (i < unrollLen - 1) {
674 
675         if (cur_lenchk_bb) {
676 
677           next_lenchk_bb =
678               BasicBlock::Create(C, "len_check", end_bb->getParent(), end_bb);
679           BranchInst::Create(end_bb, next_lenchk_bb);
680 
681         }
682 
683         next_cmp_bb =
684             BasicBlock::Create(C, "cmp_added", end_bb->getParent(), end_bb);
685         BranchInst::Create(end_bb, next_cmp_bb);
686 
687         Value *icmp =
688             cur_cmp_IRB.CreateICmpEQ(isub, ConstantInt::get(Int8Ty, 0));
689         cur_cmp_IRB.CreateCondBr(
690             icmp, next_lenchk_bb ? next_lenchk_bb : next_cmp_bb, end_bb);
691         cur_cmp_bb->getTerminator()->eraseFromParent();
692 
693       } else {
694 
695         // IRB.CreateBr(end_bb);
696 
697       }
698 
699       // add offset to varstr
700       // create load
701       // create signed isub
702       // create icmp
703       // create jcc
704       // create next_bb
705 
706     }
707 
708     /* since the call is the first instruction of the bb it is safe to
709      * replace it with a phi instruction */
710     BasicBlock::iterator ii(callInst);
711     ReplaceInstWithInst(callInst->getParent()->getInstList(), ii, PN);
712 
713   }
714 
715   return true;
716 
717 }
718 
719 #if LLVM_MAJOR >= 11                                /* use new pass manager */
720 PreservedAnalyses CompareTransform::run(Module &M, ModuleAnalysisManager &MAM) {
721 
722 #else
723 bool CompareTransform::runOnModule(Module &M) {
724 
725 #endif
726 
727   if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL)
728     printf(
729         "Running compare-transform-pass by laf.intel@gmail.com, extended by "
730         "heiko@hexco.de\n");
731   else
732     be_quiet = 1;
733 
734 #if LLVM_MAJOR >= 11                                /* use new pass manager */
735   auto PA = PreservedAnalyses::all();
736 #endif
737 
738   transformCmps(M, true, true, true, true, true);
739   verifyModule(M);
740 
741 #if LLVM_MAJOR >= 11                                /* use new pass manager */
742                      /*  if (modified) {
743 
744                          PA.abandon<XX_Manager>();
745 
746                        }*/
747 
748   return PA;
749 #else
750   return true;
751 #endif
752 
753 }
754 
755 #if LLVM_MAJOR < 11                                 /* use old pass manager */
756 static void registerCompTransPass(const PassManagerBuilder &,
757                                   legacy::PassManagerBase &PM) {
758 
759   auto p = new CompareTransform();
760   PM.add(p);
761 
762 }
763 
764 static RegisterStandardPasses RegisterCompTransPass(
765     PassManagerBuilder::EP_OptimizerLast, registerCompTransPass);
766 
767 static RegisterStandardPasses RegisterCompTransPass0(
768     PassManagerBuilder::EP_EnabledOnOptLevel0, registerCompTransPass);
769 
770   #if LLVM_VERSION_MAJOR >= 11
771 static RegisterStandardPasses RegisterCompTransPassLTO(
772     PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCompTransPass);
773   #endif
774 #endif
775 
776