aboutsummaryrefslogtreecommitdiffhomepage
path: root/lib/Core
diff options
context:
space:
mode:
authorCristian Cadar <c.cadar@imperial.ac.uk>2017-02-28 16:15:27 +0000
committerGitHub <noreply@github.com>2017-02-28 16:15:27 +0000
commite21bf6f653b9c602fe21b74ff7c389aa2430b386 (patch)
tree02b0c15d4c53e885941d2119b272a6e8e83cab16 /lib/Core
parentbff9fb9277f890f2fd9b4acd3b9d5eed0e78f967 (diff)
parent479f8068a769885e0fb50bf37f886ef839e63609 (diff)
downloadklee-e21bf6f653b9c602fe21b74ff7c389aa2430b386.tar.gz
Merge pull request #547 from delcypher/fix_alignment_of_alloc_memory
Teach KLEE to respect the requested memory alignment of allocated memory
Diffstat (limited to 'lib/Core')
-rw-r--r--lib/Core/Executor.cpp96
-rw-r--r--lib/Core/Executor.h1
-rw-r--r--lib/Core/MemoryManager.h2
3 files changed, 89 insertions, 10 deletions
diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp
index 19a5e3f8..d8a4a32c 100644
--- a/lib/Core/Executor.cpp
+++ b/lib/Core/Executor.cpp
@@ -44,6 +44,7 @@
#include "klee/Internal/Module/KModule.h"
#include "klee/Internal/Support/ErrorHandling.h"
#include "klee/Internal/Support/FloatEvaluation.h"
+#include "klee/Internal/Support/ModuleUtil.h"
#include "klee/Internal/System/Time.h"
#include "klee/Internal/System/MemoryUsage.h"
#include "klee/SolverStats.h"
@@ -592,6 +593,7 @@ void Executor::initializeGlobals(ExecutionState &state) {
for (Module::const_global_iterator i = m->global_begin(),
e = m->global_end();
i != e; ++i) {
+ size_t globalObjectAlignment = getAllocationAlignment(i);
if (i->isDeclaration()) {
// FIXME: We have no general way of handling unknown external
// symbols. If we really cared about making external stuff work
@@ -623,7 +625,9 @@ void Executor::initializeGlobals(ExecutionState &state) {
(int)i->getName().size(), i->getName().data());
}
- MemoryObject *mo = memory->allocate(size, false, true, i);
+ MemoryObject *mo = memory->allocate(size, /*isLocal=*/false,
+ /*isGlobal=*/true, /*allocSite=*/i,
+ /*alignment=*/globalObjectAlignment);
ObjectState *os = bindObjectInState(state, mo, false);
globalObjects.insert(std::make_pair(i, mo));
globalAddresses.insert(std::make_pair(i, mo->getBaseExpr()));
@@ -647,7 +651,9 @@ void Executor::initializeGlobals(ExecutionState &state) {
} else {
LLVM_TYPE_Q Type *ty = i->getType()->getElementType();
uint64_t size = kmodule->targetData->getTypeStoreSize(ty);
- MemoryObject *mo = memory->allocate(size, false, true, &*i);
+ MemoryObject *mo = memory->allocate(size, /*isLocal=*/false,
+ /*isGlobal=*/true, /*allocSite=*/&*i,
+ /*alignment=*/globalObjectAlignment);
if (!mo)
llvm::report_fatal_error("out of memory");
ObjectState *os = bindObjectInState(state, mo, false);
@@ -3149,8 +3155,11 @@ void Executor::executeAlloc(ExecutionState &state,
const ObjectState *reallocFrom) {
size = toUnique(state, size);
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(size)) {
- MemoryObject *mo = memory->allocate(CE->getZExtValue(), isLocal, false,
- state.prevPC->inst);
+ const llvm::Value *allocSite = state.prevPC->inst;
+ size_t allocationAlignment = getAllocationAlignment(allocSite);
+ MemoryObject *mo =
+ memory->allocate(CE->getZExtValue(), isLocal, /*isGlobal=*/false,
+ allocSite, allocationAlignment);
if (!mo) {
bindLocal(target, state,
ConstantExpr::alloc(0, Context::get().getPointerWidth()));
@@ -3533,10 +3542,11 @@ void Executor::runFunctionAsMain(Function *f,
Function::arg_iterator ai = f->arg_begin(), ae = f->arg_end();
if (ai!=ae) {
arguments.push_back(ConstantExpr::alloc(argc, Expr::Int32));
-
if (++ai!=ae) {
- argvMO = memory->allocate((argc+1+envc+1+1) * NumPtrBytes, false, true,
- f->begin()->begin());
+ argvMO =
+ memory->allocate((argc + 1 + envc + 1 + 1) * NumPtrBytes,
+ /*isLocal=*/false, /*isGlobal=*/true,
+ /*allocSite=*/f->begin()->begin(), /*alignment=*/8);
if (!argvMO)
klee_error("Could not allocate memory for function arguments");
@@ -3578,8 +3588,10 @@ void Executor::runFunctionAsMain(Function *f,
} else {
char *s = i<argc ? argv[i] : envp[i-(argc+1)];
int j, len = strlen(s);
-
- MemoryObject *arg = memory->allocate(len+1, false, true, state->pc->inst);
+
+ MemoryObject *arg =
+ memory->allocate(len + 1, /*isLocal=*/false, /*isGlobal=*/true,
+ /*allocSite=*/state->pc->inst, /*alignment=*/8);
if (!arg)
klee_error("Could not allocate memory for function arguments");
ObjectState *os = bindObjectInState(*state, arg, false);
@@ -3755,6 +3767,72 @@ Expr::Width Executor::getWidthForLLVMType(LLVM_TYPE_Q llvm::Type *type) const {
return kmodule->targetData->getTypeSizeInBits(type);
}
+size_t Executor::getAllocationAlignment(const llvm::Value *allocSite) const {
+ // FIXME: 8 was the previous default. We shouldn't hard code this
+ // and should fetch the default from elsewhere.
+ const size_t forcedAlignment = 8;
+ size_t alignment = 0;
+ LLVM_TYPE_Q llvm::Type *type = NULL;
+ std::string allocationSiteName(allocSite->getName().str());
+ if (const GlobalValue *GV = dyn_cast<GlobalValue>(allocSite)) {
+ alignment = GV->getAlignment();
+ if (const GlobalVariable *globalVar = dyn_cast<GlobalVariable>(GV)) {
+ // All GlobalVariables's have pointer type
+ LLVM_TYPE_Q llvm::PointerType *ptrType =
+ dyn_cast<llvm::PointerType>(globalVar->getType());
+ assert(ptrType && "globalVar's type is not a pointer");
+ type = ptrType->getElementType();
+ } else {
+ type = GV->getType();
+ }
+ } else if (const AllocaInst *AI = dyn_cast<AllocaInst>(allocSite)) {
+ alignment = AI->getAlignment();
+ type = AI->getAllocatedType();
+ } else if (isa<InvokeInst>(allocSite) || isa<CallInst>(allocSite)) {
+ // FIXME: Model the semantics of the call to use the right alignment
+ llvm::Value *allocSiteNonConst = const_cast<llvm::Value *>(allocSite);
+ const CallSite cs = (isa<InvokeInst>(allocSiteNonConst)
+ ? CallSite(cast<InvokeInst>(allocSiteNonConst))
+ : CallSite(cast<CallInst>(allocSiteNonConst)));
+ llvm::Function *fn =
+ klee::getDirectCallTarget(cs, /*moduleIsFullyLinked=*/true);
+ if (fn)
+ allocationSiteName = fn->getName().str();
+
+ klee_warning_once(fn != NULL ? fn : allocSite,
+ "Alignment of memory from call \"%s\" is not "
+ "modelled. Using alignment of %zu.",
+ allocationSiteName.c_str(), forcedAlignment);
+ alignment = forcedAlignment;
+ } else {
+ llvm_unreachable("Unhandled allocation site");
+ }
+
+ if (alignment == 0) {
+ assert(type != NULL);
+ // No specified alignment. Get the alignment for the type.
+ if (type->isSized()) {
+ alignment = kmodule->targetData->getPrefTypeAlignment(type);
+ } else {
+ klee_warning_once(allocSite, "Cannot determine memory alignment for "
+ "\"%s\". Using alignment of %zu.",
+ allocationSiteName.c_str(), forcedAlignment);
+ alignment = forcedAlignment;
+ }
+ }
+
+ // Currently we require alignment be a power of 2
+ if (!bits64::isPowerOfTwo(alignment)) {
+ klee_warning_once(allocSite, "Alignment of %zu requested for %s but this "
+ "not supported. Using alignment of %zu",
+ alignment, allocSite->getName().str().c_str(),
+ forcedAlignment);
+ alignment = forcedAlignment;
+ }
+ assert(bits64::isPowerOfTwo(alignment) &&
+ "Returned alignment must be a power of two");
+ return alignment;
+}
///
Interpreter *Interpreter::create(LLVMContext &ctx, const InterpreterOptions &opts,
diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h
index 4970b8a0..7c18ae1f 100644
--- a/lib/Core/Executor.h
+++ b/lib/Core/Executor.h
@@ -507,6 +507,7 @@ public:
std::map<const std::string*, std::set<unsigned> > &res);
Expr::Width getWidthForLLVMType(LLVM_TYPE_Q llvm::Type *type) const;
+ size_t getAllocationAlignment(const llvm::Value *allocSite) const;
};
} // End klee namespace
diff --git a/lib/Core/MemoryManager.h b/lib/Core/MemoryManager.h
index fc77b476..cc2073d8 100644
--- a/lib/Core/MemoryManager.h
+++ b/lib/Core/MemoryManager.h
@@ -40,7 +40,7 @@ public:
* memory.
*/
MemoryObject *allocate(uint64_t size, bool isLocal, bool isGlobal,
- const llvm::Value *allocSite, size_t alignment = 8);
+ const llvm::Value *allocSite, size_t alignment);
MemoryObject *allocateFixed(uint64_t address, uint64_t size,
const llvm::Value *allocSite);
void deallocate(const MemoryObject *mo);