klee
ExecutorUtil.cpp
Go to the documentation of this file.
1//===-- ExecutorUtil.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 "Context.h"
11#include "Executor.h"
12
13#include "klee/Config/Version.h"
15#include "klee/Expr/Expr.h"
16#include "klee/Module/KModule.h"
17#include "klee/Solver/Solver.h"
19
20#include "llvm/IR/Constants.h"
21#include "llvm/IR/DataLayout.h"
22#include "llvm/IR/Function.h"
23#include "llvm/IR/GetElementPtrTypeIterator.h"
24#include "llvm/IR/Instructions.h"
25#include "llvm/IR/Module.h"
26#include "llvm/IR/Operator.h"
27#include "llvm/Support/raw_ostream.h"
28
29#include <cassert>
30
31using namespace llvm;
32
33namespace klee {
34
36 const KInstruction *ki) {
37 if (!ki) {
38 KConstant* kc = kmodule->getKConstant(c);
39 if (kc)
40 ki = kc->ki;
41 }
42
43 if (const llvm::ConstantExpr *ce = dyn_cast<llvm::ConstantExpr>(c)) {
44 return evalConstantExpr(ce, ki);
45 } else {
46 if (const ConstantInt *ci = dyn_cast<ConstantInt>(c)) {
47 return ConstantExpr::alloc(ci->getValue());
48 } else if (const ConstantFP *cf = dyn_cast<ConstantFP>(c)) {
49 return ConstantExpr::alloc(cf->getValueAPF().bitcastToAPInt());
50 } else if (const GlobalValue *gv = dyn_cast<GlobalValue>(c)) {
51 auto it = globalAddresses.find(gv);
52 assert(it != globalAddresses.end());
53 return it->second;
54 } else if (isa<ConstantPointerNull>(c)) {
55 return Expr::createPointer(0);
56 } else if (isa<UndefValue>(c) || isa<ConstantAggregateZero>(c)) {
57 if (getWidthForLLVMType(c->getType()) == 0) {
58 if (isa<llvm::LandingPadInst>(ki->inst)) {
59 klee_warning_once(0, "Using zero size array fix for landingpad instruction filter");
60 return ConstantExpr::create(0, 1);
61 }
62 }
63 return ConstantExpr::create(0, getWidthForLLVMType(c->getType()));
64 } else if (const ConstantDataSequential *cds =
65 dyn_cast<ConstantDataSequential>(c)) {
66 // Handle a vector or array: first element has the smallest address,
67 // the last element the highest
68 std::vector<ref<Expr> > kids;
69 for (unsigned i = cds->getNumElements(); i != 0; --i) {
70 ref<Expr> kid = evalConstant(cds->getElementAsConstant(i - 1), ki);
71 kids.push_back(kid);
72 }
73 assert(Context::get().isLittleEndian() &&
74 "FIXME:Broken for big endian");
75 ref<Expr> res = ConcatExpr::createN(kids.size(), kids.data());
76 return cast<ConstantExpr>(res);
77 } else if (const ConstantStruct *cs = dyn_cast<ConstantStruct>(c)) {
78 const StructLayout *sl = kmodule->targetData->getStructLayout(cs->getType());
79 llvm::SmallVector<ref<Expr>, 4> kids;
80 for (unsigned i = cs->getNumOperands(); i != 0; --i) {
81 unsigned op = i-1;
82 ref<Expr> kid = evalConstant(cs->getOperand(op), ki);
83
84 uint64_t thisOffset = sl->getElementOffsetInBits(op),
85 nextOffset = (op == cs->getNumOperands() - 1)
86 ? sl->getSizeInBits()
87 : sl->getElementOffsetInBits(op+1);
88 if (nextOffset-thisOffset > kid->getWidth()) {
89 uint64_t paddingWidth = nextOffset-thisOffset-kid->getWidth();
90 kids.push_back(ConstantExpr::create(0, paddingWidth));
91 }
92
93 kids.push_back(kid);
94 }
95 assert(Context::get().isLittleEndian() &&
96 "FIXME:Broken for big endian");
97 ref<Expr> res = ConcatExpr::createN(kids.size(), kids.data());
98 return cast<ConstantExpr>(res);
99 } else if (const ConstantArray *ca = dyn_cast<ConstantArray>(c)){
100 llvm::SmallVector<ref<Expr>, 4> kids;
101 for (unsigned i = ca->getNumOperands(); i != 0; --i) {
102 unsigned op = i-1;
103 ref<Expr> kid = evalConstant(ca->getOperand(op), ki);
104 kids.push_back(kid);
105 }
106 assert(Context::get().isLittleEndian() &&
107 "FIXME:Broken for big endian");
108 ref<Expr> res = ConcatExpr::createN(kids.size(), kids.data());
109 return cast<ConstantExpr>(res);
110 } else if (const ConstantVector *cv = dyn_cast<ConstantVector>(c)) {
111 llvm::SmallVector<ref<Expr>, 8> kids;
112 const size_t numOperands = cv->getNumOperands();
113 kids.reserve(numOperands);
114 for (unsigned i = numOperands; i != 0; --i) {
115 kids.push_back(evalConstant(cv->getOperand(i - 1), ki));
116 }
117 assert(Context::get().isLittleEndian() &&
118 "FIXME:Broken for big endian");
119 ref<Expr> res = ConcatExpr::createN(numOperands, kids.data());
120 assert(isa<ConstantExpr>(res) &&
121 "result of constant vector built is not a constant");
122 return cast<ConstantExpr>(res);
123 } else if (const BlockAddress * ba = dyn_cast<BlockAddress>(c)) {
124 // return the address of the specified basic block in the specified function
125 const auto arg_bb = (BasicBlock *) ba->getOperand(1);
126 const auto res = Expr::createPointer(reinterpret_cast<std::uint64_t>(arg_bb));
127 return cast<ConstantExpr>(res);
128 } else {
129 std::string msg("Cannot handle constant ");
130 llvm::raw_string_ostream os(msg);
131 os << "'" << *c << "' at location "
132 << (ki ? ki->getSourceLocation() : "[unknown]");
133 klee_error("%s", os.str().c_str());
134 }
135 }
136 }
137
138 ref<ConstantExpr> Executor::evalConstantExpr(const llvm::ConstantExpr *ce,
139 const KInstruction *ki) {
140 llvm::Type *type = ce->getType();
141
142 ref<ConstantExpr> op1(0), op2(0), op3(0);
143 int numOperands = ce->getNumOperands();
144
145 if (numOperands > 0) op1 = evalConstant(ce->getOperand(0), ki);
146 if (numOperands > 1) op2 = evalConstant(ce->getOperand(1), ki);
147 if (numOperands > 2) op3 = evalConstant(ce->getOperand(2), ki);
148
149 /* Checking for possible errors during constant folding */
150 switch (ce->getOpcode()) {
151 case Instruction::SDiv:
152 case Instruction::UDiv:
153 case Instruction::SRem:
154 case Instruction::URem:
155 if (op2->getLimitedValue() == 0) {
156 std::string msg("Division/modulo by zero during constant folding at location ");
157 llvm::raw_string_ostream os(msg);
158 os << (ki ? ki->getSourceLocation() : "[unknown]");
159 klee_error("%s", os.str().c_str());
160 }
161 break;
162 case Instruction::Shl:
163 case Instruction::LShr:
164 case Instruction::AShr:
165 if (op2->getLimitedValue() >= op1->getWidth()) {
166 std::string msg("Overshift during constant folding at location ");
167 llvm::raw_string_ostream os(msg);
168 os << (ki ? ki->getSourceLocation() : "[unknown]");
169 klee_error("%s", os.str().c_str());
170 }
171 }
172
173 std::string msg("Unknown ConstantExpr type");
174 llvm::raw_string_ostream os(msg);
175
176 switch (ce->getOpcode()) {
177 default :
178 os << "'" << *ce << "' at location "
179 << (ki ? ki->getSourceLocation() : "[unknown]");
180 klee_error("%s", os.str().c_str());
181
182 case Instruction::Trunc:
183 return op1->Extract(0, getWidthForLLVMType(type));
184 case Instruction::ZExt: return op1->ZExt(getWidthForLLVMType(type));
185 case Instruction::SExt: return op1->SExt(getWidthForLLVMType(type));
186 case Instruction::Add: return op1->Add(op2);
187 case Instruction::Sub: return op1->Sub(op2);
188 case Instruction::Mul: return op1->Mul(op2);
189 case Instruction::SDiv: return op1->SDiv(op2);
190 case Instruction::UDiv: return op1->UDiv(op2);
191 case Instruction::SRem: return op1->SRem(op2);
192 case Instruction::URem: return op1->URem(op2);
193 case Instruction::And: return op1->And(op2);
194 case Instruction::Or: return op1->Or(op2);
195 case Instruction::Xor: return op1->Xor(op2);
196 case Instruction::Shl: return op1->Shl(op2);
197 case Instruction::LShr: return op1->LShr(op2);
198 case Instruction::AShr: return op1->AShr(op2);
199 case Instruction::BitCast: return op1;
200
201 case Instruction::IntToPtr:
202 return op1->ZExt(getWidthForLLVMType(type));
203
204 case Instruction::PtrToInt:
205 return op1->ZExt(getWidthForLLVMType(type));
206
207 case Instruction::GetElementPtr: {
208 ref<ConstantExpr> base = op1->ZExt(Context::get().getPointerWidth());
209 for (gep_type_iterator ii = gep_type_begin(ce), ie = gep_type_end(ce);
210 ii != ie; ++ii) {
211 ref<ConstantExpr> indexOp =
212 evalConstant(cast<Constant>(ii.getOperand()), ki);
213 if (indexOp->isZero())
214 continue;
215
216 // Handle a struct index, which adds its field offset to the pointer.
217 if (auto STy = ii.getStructTypeOrNull()) {
218 unsigned ElementIdx = indexOp->getZExtValue();
219 const StructLayout *SL = kmodule->targetData->getStructLayout(STy);
220 base = base->Add(
221 ConstantExpr::alloc(APInt(Context::get().getPointerWidth(),
222 SL->getElementOffset(ElementIdx))));
223 continue;
224 }
225
226 // For array or vector indices, scale the index by the size of the type.
227 // Indices can be negative
228 base = base->Add(indexOp->SExt(Context::get().getPointerWidth())
230 APInt(Context::get().getPointerWidth(),
231 kmodule->targetData->getTypeAllocSize(
232 ii.getIndexedType())))));
233 }
234 return base;
235 }
236
237 case Instruction::ICmp: {
238 switch(ce->getPredicate()) {
239 default: assert(0 && "unhandled ICmp predicate");
240 case ICmpInst::ICMP_EQ: return op1->Eq(op2);
241 case ICmpInst::ICMP_NE: return op1->Ne(op2);
242 case ICmpInst::ICMP_UGT: return op1->Ugt(op2);
243 case ICmpInst::ICMP_UGE: return op1->Uge(op2);
244 case ICmpInst::ICMP_ULT: return op1->Ult(op2);
245 case ICmpInst::ICMP_ULE: return op1->Ule(op2);
246 case ICmpInst::ICMP_SGT: return op1->Sgt(op2);
247 case ICmpInst::ICMP_SGE: return op1->Sge(op2);
248 case ICmpInst::ICMP_SLT: return op1->Slt(op2);
249 case ICmpInst::ICMP_SLE: return op1->Sle(op2);
250 }
251 }
252
253 case Instruction::Select:
254 return op1->isTrue() ? op2 : op3;
255
256 case Instruction::FAdd:
257 case Instruction::FSub:
258 case Instruction::FMul:
259 case Instruction::FDiv:
260 case Instruction::FRem:
261 case Instruction::FPTrunc:
262 case Instruction::FPExt:
263 case Instruction::UIToFP:
264 case Instruction::SIToFP:
265 case Instruction::FPToUI:
266 case Instruction::FPToSI:
267 case Instruction::FCmp:
268 assert(0 && "floating point ConstantExprs unsupported");
269 }
270 llvm_unreachable("Unsupported expression in evalConstantExpr");
271 return op1;
272 }
273}
static ref< Expr > createN(unsigned nKids, const ref< Expr > kids[])
Shortcuts to create larger concats. The chain returned is unbalanced to the right.
Definition: Expr.cpp:647
static ref< ConstantExpr > create(uint64_t v, Width w)
Definition: Expr.h:1079
static ref< ConstantExpr > alloc(const llvm::APInt &v)
Definition: Expr.h:1065
Expr::Width getPointerWidth() const
Returns width of the pointer in bits.
Definition: Context.h:41
static const Context & get()
get - Return the global singleton instance of the Context.
Definition: Context.cpp:30
std::map< const llvm::GlobalValue *, ref< ConstantExpr > > globalAddresses
Definition: Executor.h:146
Expr::Width getWidthForLLVMType(llvm::Type *type) const
Definition: Executor.cpp:4584
ref< klee::ConstantExpr > evalConstantExpr(const llvm::ConstantExpr *c, const KInstruction *ki=NULL)
std::unique_ptr< KModule > kmodule
Definition: Executor.h:107
ref< klee::ConstantExpr > evalConstant(const llvm::Constant *c, const KInstruction *ki=NULL)
virtual Width getWidth() const =0
static ref< ConstantExpr > createPointer(uint64_t v)
Definition: Context.cpp:46
KInstruction * ki
Definition: KModule.h:77
Definition: main.cpp:291
gep_type_iterator gep_type_begin(const llvm::User *GEP)
void klee_error(const char *msg,...) __attribute__((format(printf
void void void void klee_warning_once(const void *id, const char *msg,...) __attribute__((format(printf
gep_type_iterator gep_type_end(const llvm::User *GEP)
llvm::Instruction * inst
Definition: KInstruction.h:34
std::string getSourceLocation() const