about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
authorDan Liew <daniel.liew@imperial.ac.uk>2015-10-17 18:32:19 +0100
committerDan Liew <daniel.liew@imperial.ac.uk>2015-10-17 18:46:34 +0100
commit2a7c7f81a70f1266cf67471861bffc8f2192ce18 (patch)
tree10b1702040e82d859cde6fffa460244ea6b627df
parent50b9e95064a8a312c365fda57ed5729cd91706ba (diff)
downloadklee-2a7c7f81a70f1266cf67471861bffc8f2192ce18.tar.gz
Implement gross hack to make it possible to execute code compiled
with -m32 (i.e. for i386). Previously if this was attempt allocations
in the program being executed by KLEE would hit an assertion because
malloc() would return an address that doesn't fit in a 32-bit pointer.

The interface of MemoryManager has been changed so that it is necessary
to specify the pointer size on creation. The implementation has been
changed to use a MASSIVE HACK when the pointer width is less than
64-bits.
-rw-r--r--lib/Core/Executor.cpp6
-rw-r--r--lib/Core/MemoryManager.cpp17
-rw-r--r--lib/Core/MemoryManager.h3
-rw-r--r--test/Feature/32BitAlloc.c15
4 files changed, 37 insertions, 4 deletions
diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp
index 49e526f5..29e6486f 100644
--- a/lib/Core/Executor.cpp
+++ b/lib/Core/Executor.cpp
@@ -276,6 +276,7 @@ Executor::Executor(const InterpreterOptions &opts,
     interpreterHandler(ih),
     searcher(0),
     externalDispatcher(new ExternalDispatcher()),
+    memory(0), // Can't be initialised until we know the pointer size
     statsTracker(0),
     pathWriter(0),
     symPathWriter(0),
@@ -337,7 +338,6 @@ Executor::Executor(const InterpreterOptions &opts,
   
   this->solver = new TimingSolver(solver, EqualitySubstitution);
 
-  memory = new MemoryManager();
 }
 
 
@@ -355,7 +355,7 @@ const Module *Executor::setModule(llvm::Module *module,
 #endif
   Context::initialize(TD->isLittleEndian(),
                       (Expr::Width) TD->getPointerSizeInBits());
-
+  memory = new MemoryManager(TD->getPointerSizeInBits());
   specialFunctionHandler = new SpecialFunctionHandler(*this);
 
   specialFunctionHandler->prepare();
@@ -3415,7 +3415,7 @@ void Executor::runFunctionAsMain(Function *f,
 
   // hack to clear memory objects
   delete memory;
-  memory = new MemoryManager();
+  memory = new MemoryManager(Context::get().getPointerWidth());
   
   globalObjects.clear();
   globalAddresses.clear();
diff --git a/lib/Core/MemoryManager.cpp b/lib/Core/MemoryManager.cpp
index a1198007..0caa504d 100644
--- a/lib/Core/MemoryManager.cpp
+++ b/lib/Core/MemoryManager.cpp
@@ -12,16 +12,33 @@
 #include "CoreStats.h"
 #include "Memory.h"
 #include "MemoryManager.h"
+#include "Context.h"
 
 #include "klee/ExecutionState.h"
 #include "klee/Expr.h"
 #include "klee/Solver.h"
 
 #include "llvm/Support/CommandLine.h"
+#include "malloc.h"
 
 using namespace klee;
 
 /***/
+MemoryManager::MemoryManager(size_t pointerBitWidth) :
+  pointerBitWidth(pointerBitWidth) {
+  if (pointerBitWidth < 64) {
+    // FIXME: KLEE should implement it's own memory manager for
+    // the program we are executing and not invoke malloc so
+    // we have finer control over the addresses we use.
+    // HACK:
+    // Try make sure malloc() gives us back
+    // addresses that fit in a 32-bit integer when running
+    // 32-bit code.
+    // This works by preventing malloc() from using mmap()
+    // so it uses sbrk() instead... gross
+    mallopt(M_MMAP_MAX, 0);
+  }
+}
 
 MemoryManager::~MemoryManager() { 
   while (!objects.empty()) {
diff --git a/lib/Core/MemoryManager.h b/lib/Core/MemoryManager.h
index f398db62..d87ebe41 100644
--- a/lib/Core/MemoryManager.h
+++ b/lib/Core/MemoryManager.h
@@ -24,9 +24,10 @@ namespace klee {
   private:
     typedef std::set<MemoryObject*> objects_ty;
     objects_ty objects;
+    size_t pointerBitWidth;
 
   public:
-    MemoryManager() {}
+    MemoryManager(size_t pointerBitWidth);
     ~MemoryManager();
 
     MemoryObject *allocate(uint64_t size, bool isLocal, bool isGlobal,
diff --git a/test/Feature/32BitAlloc.c b/test/Feature/32BitAlloc.c
new file mode 100644
index 00000000..311dc239
--- /dev/null
+++ b/test/Feature/32BitAlloc.c
@@ -0,0 +1,15 @@
+// RUN: %llvmgcc %s -emit-llvm -m32 -O0 -c -o %t1.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out %t1.bc
+
+// This simply tests that allocation works when
+// running 32-bit code
+
+// FIXME: This test only needs to run on x86_64
+int main() {
+  int a[100000];
+  for (int i=0; i < 5000; ++i) {
+    a[i] = i;
+  }
+  return 0;
+}