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