klee
MemoryManager.cpp
Go to the documentation of this file.
1//===-- MemoryManager.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 "MemoryManager.h"
11
12#include "CoreStats.h"
13#include "Memory.h"
14
15#include "klee/Expr/Expr.h"
17
18#include "llvm/Support/CommandLine.h"
19#include "llvm/Support/MathExtras.h"
20
21#include <inttypes.h>
22#include <sys/mman.h>
23
24using namespace klee;
25
26namespace {
27
28llvm::cl::OptionCategory MemoryCat("Memory management options",
29 "These options control memory management.");
30
31llvm::cl::opt<bool> DeterministicAllocation(
32 "allocate-determ",
33 llvm::cl::desc("Allocate memory deterministically (default=false)"),
34 llvm::cl::init(false), llvm::cl::cat(MemoryCat));
35
36llvm::cl::opt<unsigned> DeterministicAllocationSize(
37 "allocate-determ-size",
38 llvm::cl::desc(
39 "Preallocated memory for deterministic allocation in MB (default=100)"),
40 llvm::cl::init(100), llvm::cl::cat(MemoryCat));
41
42llvm::cl::opt<bool> NullOnZeroMalloc(
43 "return-null-on-zero-malloc",
44 llvm::cl::desc("Returns NULL if malloc(0) is called (default=false)"),
45 llvm::cl::init(false), llvm::cl::cat(MemoryCat));
46
47llvm::cl::opt<unsigned> RedzoneSize(
48 "redzone-size",
49 llvm::cl::desc("Set the size of the redzones to be added after each "
50 "allocation (in bytes). This is important to detect "
51 "out-of-bounds accesses (default=10)"),
52 llvm::cl::init(10), llvm::cl::cat(MemoryCat));
53
54llvm::cl::opt<unsigned long long> DeterministicStartAddress(
55 "allocate-determ-start-address",
56 llvm::cl::desc("Start address for deterministic allocation. Has to be page "
57 "aligned (default=0x7ff30000000)"),
58 llvm::cl::init(0x7ff30000000), llvm::cl::cat(MemoryCat));
59} // namespace
60
61/***/
62MemoryManager::MemoryManager(ArrayCache *_arrayCache)
63 : arrayCache(_arrayCache), deterministicSpace(0), nextFreeSlot(0),
64 spaceSize(DeterministicAllocationSize.getValue() * 1024 * 1024) {
65 if (DeterministicAllocation) {
66 // Page boundary
67 void *expectedAddress = (void *)DeterministicStartAddress.getValue();
68
69 char *newSpace =
70 (char *)mmap(expectedAddress, spaceSize, PROT_READ | PROT_WRITE,
71 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
72
73 if (newSpace == MAP_FAILED) {
74 klee_error("Couldn't mmap() memory for deterministic allocations");
75 }
76 if (expectedAddress != newSpace && expectedAddress != 0) {
77 klee_error("Could not allocate memory deterministically");
78 }
79
80 klee_message("Deterministic memory allocation starting from %p", newSpace);
81 deterministicSpace = newSpace;
82 nextFreeSlot = newSpace;
83 }
84}
85
87 while (!objects.empty()) {
88 MemoryObject *mo = *objects.begin();
89 if (!mo->isFixed && !DeterministicAllocation)
90 free((void *)mo->address);
91 objects.erase(mo);
92 delete mo;
93 }
94
95 if (DeterministicAllocation)
97}
98
99MemoryObject *MemoryManager::allocate(uint64_t size, bool isLocal,
100 bool isGlobal,
101 const llvm::Value *allocSite,
102 size_t alignment) {
103 if (size > 10 * 1024 * 1024)
104 klee_warning_once(0, "Large alloc: %" PRIu64
105 " bytes. KLEE may run out of memory.",
106 size);
107
108 // Return NULL if size is zero, this is equal to error during allocation
109 if (NullOnZeroMalloc && size == 0)
110 return 0;
111
112 if (!llvm::isPowerOf2_64(alignment)) {
113 klee_warning("Only alignment of power of two is supported");
114 return 0;
115 }
116
117 uint64_t address = 0;
118 if (DeterministicAllocation) {
119 address = llvm::alignTo((uint64_t)nextFreeSlot + alignment - 1, alignment);
120
121 // Handle the case of 0-sized allocations as 1-byte allocations.
122 // This way, we make sure we have this allocation between its own red zones
123 size_t alloc_size = std::max(size, (uint64_t)1);
124 if ((char *)address + alloc_size < deterministicSpace + spaceSize) {
125 nextFreeSlot = (char *)address + alloc_size + RedzoneSize;
126 } else {
127 klee_warning_once(0, "Couldn't allocate %" PRIu64
128 " bytes. Not enough deterministic space left.",
129 size);
130 address = 0;
131 }
132 } else {
133 // Use malloc for the standard case
134 if (alignment <= 8)
135 address = (uint64_t)malloc(size);
136 else {
137 int res = posix_memalign((void **)&address, alignment, size);
138 if (res < 0) {
139 klee_warning("Allocating aligned memory failed.");
140 address = 0;
141 }
142 }
143 }
144
145 if (!address)
146 return 0;
147
149 MemoryObject *res = new MemoryObject(address, size, isLocal, isGlobal, false,
150 allocSite, this);
151 objects.insert(res);
152 return res;
153}
154
155MemoryObject *MemoryManager::allocateFixed(uint64_t address, uint64_t size,
156 const llvm::Value *allocSite) {
157#ifndef NDEBUG
158 for (objects_ty::iterator it = objects.begin(), ie = objects.end(); it != ie;
159 ++it) {
160 MemoryObject *mo = *it;
161 if (address + size > mo->address && address < mo->address + mo->size)
162 klee_error("Trying to allocate an overlapping object");
163 }
164#endif
165
167 MemoryObject *res =
168 new MemoryObject(address, size, false, true, true, allocSite, this);
169 objects.insert(res);
170 return res;
171}
172
173void MemoryManager::deallocate(const MemoryObject *mo) { assert(0); }
174
176 if (objects.find(mo) != objects.end()) {
177 if (!mo->isFixed && !DeterministicAllocation)
178 free((void *)mo->address);
179 objects.erase(mo);
180 }
181}
182
185}
Provides an interface for creating and destroying Array objects.
Definition: ArrayCache.h:31
MemoryObject * allocateFixed(uint64_t address, uint64_t size, const llvm::Value *allocSite)
size_t getUsedDeterministicSize()
void deallocate(const MemoryObject *mo)
void markFreed(MemoryObject *mo)
MemoryObject * allocate(uint64_t size, bool isLocal, bool isGlobal, const llvm::Value *allocSite, size_t alignment)
unsigned size
size in bytes
Definition: Memory.h:52
uint64_t address
Definition: Memory.h:49
Statistic allocations
Definition: main.cpp:291
void klee_message(const char *msg,...) __attribute__((format(printf
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
void void void klee_warning(const char *msg,...) __attribute__((format(printf