klee
Checks.cpp
Go to the documentation of this file.
1//===-- Checks.cpp --------------------------------------------------------===//
2//
3// The KLEE Symbolic Virtual Machine
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "Passes.h"
11
12#include "klee/Config/Version.h"
13
14#include "KLEEIRMetaData.h"
15
16#include "llvm/IR/Constants.h"
17#include "llvm/IR/DataLayout.h"
18#include "llvm/IR/DerivedTypes.h"
19#include "llvm/IR/Function.h"
20#include "llvm/IR/IRBuilder.h"
21#include "llvm/IR/InstrTypes.h"
22#include "llvm/IR/Instruction.h"
23#include "llvm/IR/Instructions.h"
24#include "llvm/IR/IntrinsicInst.h"
25#include "llvm/IR/LLVMContext.h"
26#include "llvm/IR/Module.h"
27#include "llvm/IR/Type.h"
28#include "llvm/Pass.h"
29#include "llvm/Transforms/Scalar.h"
30#include "llvm/Transforms/Utils/BasicBlockUtils.h"
31
32using namespace llvm;
33using namespace klee;
34
35char DivCheckPass::ID;
36
37bool DivCheckPass::runOnModule(Module &M) {
38 std::vector<llvm::BinaryOperator *> divInstruction;
39
40 for (auto &F : M) {
41 for (auto &BB : F) {
42 for (auto &I : BB) {
43 auto binOp = dyn_cast<BinaryOperator>(&I);
44 if (!binOp)
45 continue;
46
47 // find all [s|u][div|rem] instructions
48 auto opcode = binOp->getOpcode();
49 if (opcode != Instruction::SDiv && opcode != Instruction::UDiv &&
50 opcode != Instruction::SRem && opcode != Instruction::URem)
51 continue;
52
53 // Check if the operand is constant and not zero, skip in that case.
54 const auto &operand = binOp->getOperand(1);
55 if (const auto &coOp = dyn_cast<llvm::Constant>(operand)) {
56 if (!coOp->isZeroValue())
57 continue;
58 }
59
60 // Check if the operand is already checked by "klee_div_zero_check"
61 if (KleeIRMetaData::hasAnnotation(I, "klee.check.div", "True"))
62 continue;
63 divInstruction.push_back(binOp);
64 }
65 }
66 }
67
68 // If nothing to do, return
69 if (divInstruction.empty())
70 return false;
71
72 LLVMContext &ctx = M.getContext();
73 KleeIRMetaData md(ctx);
74 auto divZeroCheckFunction =
75 M.getOrInsertFunction("klee_div_zero_check", Type::getVoidTy(ctx),
76 Type::getInt64Ty(ctx));
77
78 for (auto &divInst : divInstruction) {
79 llvm::IRBuilder<> Builder(divInst /* Inserts before divInst*/);
80 auto denominator =
81 Builder.CreateIntCast(divInst->getOperand(1), Type::getInt64Ty(ctx),
82 false, /* sign doesn't matter */
83 "int_cast_to_i64");
84 Builder.CreateCall(divZeroCheckFunction, denominator);
85 md.addAnnotation(*divInst, "klee.check.div", "True");
86 }
87
88 return true;
89}
90
92
94 std::vector<llvm::BinaryOperator *> shiftInstructions;
95 for (auto &F : M) {
96 for (auto &BB : F) {
97 for (auto &I : BB) {
98 auto binOp = dyn_cast<BinaryOperator>(&I);
99 if (!binOp)
100 continue;
101
102 // find all shift instructions
103 auto opcode = binOp->getOpcode();
104 if (opcode != Instruction::Shl && opcode != Instruction::LShr &&
105 opcode != Instruction::AShr)
106 continue;
107
108 // Check if the operand is constant and not zero, skip in that case
109 auto operand = binOp->getOperand(1);
110 if (auto coOp = dyn_cast<llvm::ConstantInt>(operand)) {
111 auto typeWidth =
112 binOp->getOperand(0)->getType()->getScalarSizeInBits();
113 // If the constant shift is positive and smaller,equal the type width,
114 // we can ignore this instruction
115 if (!coOp->isNegative() && coOp->getZExtValue() < typeWidth)
116 continue;
117 }
118
119 if (KleeIRMetaData::hasAnnotation(I, "klee.check.shift", "True"))
120 continue;
121
122 shiftInstructions.push_back(binOp);
123 }
124 }
125 }
126
127 if (shiftInstructions.empty())
128 return false;
129
130 // Retrieve the checker function
131 auto &ctx = M.getContext();
132 KleeIRMetaData md(ctx);
133 auto overshiftCheckFunction = M.getOrInsertFunction(
134 "klee_overshift_check", Type::getVoidTy(ctx), Type::getInt64Ty(ctx),
135 Type::getInt64Ty(ctx));
136
137 for (auto &shiftInst : shiftInstructions) {
138 llvm::IRBuilder<> Builder(shiftInst);
139
140 std::vector<llvm::Value *> args;
141
142 // Determine bit width of first operand
143 uint64_t bitWidth = shiftInst->getOperand(0)->getType()->getScalarSizeInBits();
144 auto bitWidthC = ConstantInt::get(Type::getInt64Ty(ctx), bitWidth, false);
145 args.push_back(bitWidthC);
146
147 auto shiftValue =
148 Builder.CreateIntCast(shiftInst->getOperand(1), Type::getInt64Ty(ctx),
149 false, /* sign doesn't matter */
150 "int_cast_to_i64");
151 args.push_back(shiftValue);
152
153 Builder.CreateCall(overshiftCheckFunction, args);
154 md.addAnnotation(*shiftInst, "klee.check.shift", "True");
155 }
156
157 return true;
158}
Handles KLEE-specific LLVM IR meta-data.
static bool hasAnnotation(const llvm::Instruction &inst, llvm::StringRef key, llvm::StringRef value)
Check if the instruction has the key/value meta data.
void addAnnotation(llvm::Instruction &inst, llvm::StringRef key, llvm::StringRef value)
bool runOnModule(llvm::Module &M) override
Definition: Checks.cpp:93
Definition: main.cpp:291