blob: 00fe07b32865a8cf3c59b057f6d5107533b30834 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
//===-- MemoryUsage.cpp ---------------------------------------------------===//
//
// The KLEE Symbolic Virtual Machine
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "klee/System/MemoryUsage.h"
#include "klee/Config/config.h"
#include "klee/Support/ErrorHandling.h"
#ifdef HAVE_GPERFTOOLS_MALLOC_EXTENSION_H
#include "gperftools/malloc_extension.h"
#endif
#ifdef HAVE_MALLINFO
#include <malloc.h>
#endif
#ifdef HAVE_MALLOC_ZONE_STATISTICS
#include <malloc/malloc.h>
#endif
// ASan Support
//
// When building with ASan the `mallinfo()` function is intercepted and always
// reports zero so we can't use that to report KLEE's memory usage. Instead we
// will use ASan's public interface to query how much memory has been
// allocated.
//
// Unfortunately the interface is dependent on the compiler version. It is also
// unfortunate that the way to detect compilation with ASan differs between
// compilers. The preprocessor code below tries to determine if ASan is enabled
// and if so which interface should be used.
//
// If ASan is enabled the `KLEE_ASAN_BUILD` macro will be defined other it will
// be undefined. If `KLEE_ASAN_BUILD` is defined then the
// `ASAN_GET_ALLOCATED_MEM_FUNCTION` macro will defined to the name of the ASan
// function that can be called to get memory allocation
// Make sure we start with the macro being undefined.
#undef KLEE_ASAN_BUILD
// Clang and ASan
#if defined(__has_feature)
# if __has_feature(address_sanitizer)
# if __has_include("sanitizer/allocator_interface.h")
# include <sanitizer/allocator_interface.h>
// Modern interface
# define ASAN_GET_ALLOCATED_MEM_FUNCTION __sanitizer_get_current_allocated_bytes
# else
# include <sanitizer/asan_interface.h>
// Deprecated interface.
# define ASAN_GET_ALLOCATED_MEM_FUNCTION __asan_get_current_allocated_bytes
# endif /* has_include("sanitizer/allocator_interface.h") */
# define KLEE_ASAN_BUILD
# endif /* __has_feature(address_sanitizer) */
#endif /* defined(__has_feature) */
// For GCC and ASan
#ifndef KLEE_ASAN_BUILD
# if defined(__SANITIZE_ADDRESS__)
// HACK: GCC doesn't ship `allocator_interface.h` or `asan_interface.h` so
// just provide the proto-types here.
extern "C" {
size_t __sanitizer_get_current_allocated_bytes();
size_t __asan_get_current_allocated_bytes(); // Deprecated.
}
// HACK: Guess which function to use based on GCC version
# if __GNUC__ > 4
// Tested with gcc 5.2, 5.4, and 6.2.1
// Modern interface
# define ASAN_GET_ALLOCATED_MEM_FUNCTION __sanitizer_get_current_allocated_bytes
# else
// Tested with gcc 4.8 and 4.9
// Deprecated interface
# define ASAN_GET_ALLOCATED_MEM_FUNCTION __asan_get_current_allocated_bytes
# endif
# define KLEE_ASAN_BUILD
# endif /* defined(__SANITIZE_ADDRESS__) */
#endif /* ndef KLEE_ASAN_BUILD */
using namespace klee;
size_t util::GetTotalMallocUsage() {
#ifdef KLEE_ASAN_BUILD
// When building with ASan on Linux `mallinfo()` just returns 0 so use ASan runtime
// function instead to get used memory.
return ASAN_GET_ALLOCATED_MEM_FUNCTION();
#endif
#ifdef HAVE_GPERFTOOLS_MALLOC_EXTENSION_H
size_t value = 0;
MallocExtension::instance()->GetNumericProperty(
"generic.current_allocated_bytes", &value);
return value;
#elif defined(HAVE_MALLINFO)
struct mallinfo mi = ::mallinfo();
// The malloc implementation in glibc (pmalloc2)
// does not include mmap()'ed memory in mi.uordblks
// but other implementations (e.g. tcmalloc) do.
#if defined(__GLIBC__)
return (size_t)(unsigned)mi.uordblks + (unsigned)mi.hblkhd;
#else
return (unsigned)mi.uordblks;
#endif
#elif defined(HAVE_MALLOC_ZONE_STATISTICS)
// Memory usage on macOS
malloc_statistics_t stats;
malloc_zone_t **zones;
unsigned int num_zones;
if (malloc_get_all_zones(0, nullptr, (vm_address_t **)&zones, &num_zones) !=
KERN_SUCCESS)
klee_error("malloc_get_all_zones failed.");
int total = 0;
for (unsigned i = 0; i < num_zones; i++) {
malloc_zone_statistics(zones[i], &stats);
total += stats.size_in_use;
}
return total;
#else // HAVE_MALLINFO
#warning Cannot get malloc info on this platform
return 0;
#endif
}
|