From f751f9351f0176a3109e260a6e8e9727fc9fb4ea Mon Sep 17 00:00:00 2001 From: Martin Nowack Date: Sun, 29 Oct 2017 22:06:16 +0100 Subject: Fix getelementptr for array or vector indices Rewrote code based on: llvm::GEPOperator::accumulateConstantOffset(): Handle signed offset correctly. --- lib/Core/ExecutorUtil.cpp | 51 ++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 25 deletions(-) (limited to 'lib/Core/ExecutorUtil.cpp') diff --git a/lib/Core/ExecutorUtil.cpp b/lib/Core/ExecutorUtil.cpp index 4f51ecb6..92dee5ac 100644 --- a/lib/Core/ExecutorUtil.cpp +++ b/lib/Core/ExecutorUtil.cpp @@ -19,18 +19,22 @@ #include "klee/Internal/Module/KModule.h" #include "klee/Internal/Support/ErrorHandling.h" -#include "klee/util/GetElementPtrTypeIterator.h" -#include "llvm/IR/Function.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" -#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Operator.h" +#if LLVM_VERSION_CODE < LLVM_VERSION(3, 5) +#include "llvm/Support/GetElementPtrTypeIterator.h" +#else +#include "llvm/IR/GetElementPtrTypeIterator.h" +#endif #include "llvm/Support/raw_ostream.h" #include -using namespace klee; using namespace llvm; namespace klee { @@ -188,34 +192,31 @@ namespace klee { case Instruction::GetElementPtr: { ref base = op1->ZExt(Context::get().getPointerWidth()); - for (gep_type_iterator ii = gep_type_begin(ce), ie = gep_type_end(ce); ii != ie; ++ii) { - ref addend = - ConstantExpr::alloc(0, Context::get().getPointerWidth()); - - if (StructType *st = dyn_cast(*ii)) { - const StructLayout *sl = kmodule->targetData->getStructLayout(st); - const ConstantInt *ci = cast(ii.getOperand()); - - addend = ConstantExpr::alloc(sl->getElementOffset((unsigned) - ci->getZExtValue()), - Context::get().getPointerWidth()); - } else { - const SequentialType *set = cast(*ii); - ref index = + ref indexOp = evalConstant(cast(ii.getOperand()), ki); - unsigned elementSize = - kmodule->targetData->getTypeStoreSize(set->getElementType()); + if (indexOp->isZero()) + continue; - index = index->ZExt(Context::get().getPointerWidth()); - addend = index->Mul(ConstantExpr::alloc(elementSize, - Context::get().getPointerWidth())); + // Handle a struct index, which adds its field offset to the pointer. + if (StructType *STy = dyn_cast(*ii)) { + unsigned ElementIdx = indexOp->getZExtValue(); + const StructLayout *SL = kmodule->targetData->getStructLayout(STy); + base = base->Add( + ConstantExpr::alloc(APInt(Context::get().getPointerWidth(), + SL->getElementOffset(ElementIdx)))); + continue; } - base = base->Add(addend); + // For array or vector indices, scale the index by the size of the type. + // Indices can be negative + base = base->Add(indexOp->SExt(Context::get().getPointerWidth()) + ->Mul(ConstantExpr::alloc( + APInt(Context::get().getPointerWidth(), + kmodule->targetData->getTypeAllocSize( + ii.getIndexedType()))))); } - return base; } -- cgit 1.4.1