Skip to content

Commit 1804859

Browse files
committed
Add asan and valgrind annotations for tracking memory
1 parent 317afb8 commit 1804859

File tree

5 files changed

+148
-3
lines changed

5 files changed

+148
-3
lines changed

.github/workflows/nightly.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ jobs:
4040
-DUMF_BUILD_LIBUMF_POOL_DISJOINT=ON
4141
-DUMF_BUILD_LIBUMF_POOL_JEMALLOC=ON
4242
-DUMF_BUILD_LEVEL_ZERO_PROVIDER=OFF
43+
-DUSE_VALGRIND=1
4344
4445
- name: Build
4546
run: cmake --build ${{github.workspace}}/build --config Debug -j$(nproc)

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ option(USE_ASAN "Enable AddressSanitizer checks" OFF)
2323
option(USE_UBSAN "Enable UndefinedBehaviorSanitizer checks" OFF)
2424
option(USE_TSAN "Enable ThreadSanitizer checks" OFF)
2525
option(USE_MSAN "Enable MemorySanitizer checks" OFF)
26+
option(USE_VALGRIND "Enable Valgrind instrumentation" OFF)
2627

2728
# For using the options listed in the OPTIONS_REQUIRING_CXX variable
2829
# a C++17 compiler is required. Moreover, if these options are not set,

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ List of options provided by CMake:
105105
| USE_UBSAN | Enable UndefinedBehaviorSanitizer checks | ON/OFF | OFF |
106106
| USE_TSAN | Enable ThreadSanitizer checks | ON/OFF | OFF |
107107
| USE_MSAN | Enable MemorySanitizer checks | ON/OFF | OFF |
108+
| USE_VALGRIND | Enable Valgrind instrumentation | ON/OFF | OFF |
108109

109110
## Architecture: memory pools and providers
110111

src/utils/CMakeLists.txt

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@ set(UMF_UTILS_SOURCES_WINDOWS
1717
utils_windows_math.c
1818
)
1919

20+
if(USE_VALGRIND)
21+
if (USE_ASAN OR USE_TSAN OR USE_UBSAN OR USE_MSAN)
22+
message(FATAL_ERROR "Cannot use valgrind and sanitizers together")
23+
endif()
24+
25+
if(PkgConfig_FOUND)
26+
pkg_check_modules(VALGRIND valgrind)
27+
endif()
28+
if(NOT VALGRIND_FOUND)
29+
find_package(VALGRIND REQUIRED valgrind)
30+
endif()
31+
endif()
32+
2033
if(LINUX OR MACOSX)
2134
set(UMF_UTILS_SOURCES ${UMF_UTILS_SOURCES_POSIX})
2235
elseif(WINDOWS)
@@ -30,11 +43,16 @@ add_umf_library(NAME umf_utils
3043

3144
add_library(${PROJECT_NAME}::utils ALIAS umf_utils)
3245

33-
target_include_directories(umf_utils PUBLIC
46+
target_include_directories(umf_utils PUBLIC
47+
${VALGRIND_INCLUDE_DIRS}
3448
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
3549
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
3650
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
3751
)
3852

53+
if(USE_VALGRIND)
54+
target_compile_definitions(umf_utils PUBLIC UMF_VG_ENABLED=1)
55+
endif()
56+
3957
install(TARGETS umf_utils
4058
EXPORT ${PROJECT_NAME}-targets)

src/utils/utils_sanitizers.h

Lines changed: 126 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,156 @@
1313
#define __SANITIZE_THREAD__ 1
1414
#endif
1515
#endif
16+
#if __has_feature(address_sanitizer)
17+
#ifndef __SANITIZE_ADDRESS__
18+
#define __SANITIZE_ADDRESS__ 1
19+
#endif
20+
#endif
21+
#endif
22+
23+
#if UMF_VG_ENABLED
24+
#undef UMF_VG_MEMCHECK_ENABLED
25+
#undef UMF_VG_HELGRIND_ENABLED
26+
#undef UMF_VG_DRD_ENABLED
27+
28+
#define UMF_VG_MEMCHECK_ENABLED 1
29+
#define UMF_VG_HELGRIND_ENABLED 1
30+
#define UMF_VG_DRD_ENABLED 1
31+
#endif
32+
33+
#if UMF_VG_MEMCHECK_ENABLED || UMF_VG_HELGRIND_ENABLED || UMF_VG_DRD_ENABLED
34+
#define UMF_ANY_VG_TOOL_ENABLED 1
35+
#endif
36+
37+
#if UMF_ANY_VG_TOOL_ENABLED
38+
#include <valgrind.h>
39+
#endif
40+
41+
#if UMF_VG_MEMCHECK_ENABLED
42+
#include <memcheck.h>
43+
#endif
44+
45+
#if UMF_VG_HELGRIND_ENABLED
46+
#include <helgrind.h>
47+
#endif
48+
49+
#if UMF_VG_DRD_ENABLED
50+
#include <drd.h>
1651
#endif
1752

1853
#if __SANITIZE_THREAD__
1954
#include <sanitizer/tsan_interface.h>
2055
#endif
2156

57+
#if __SANITIZE_ADDRESS__
58+
#include <sanitizer/asan_interface.h>
59+
#endif
60+
61+
#if UMF_VG_MEMCHECK_ENABLED
62+
#define VALGRIND_DO_MALLOCLIKE_BLOCK VALGRIND_MALLOCLIKE_BLOCK
63+
#define VALGRIND_DO_FREELIKE_BLOCK VALGRIND_FREELIKE_BLOCK
64+
#define VALGRIND_DO_CREATE_MEMPOOL VALGRIND_CREATE_MEMPOOL
65+
#define VALGRIND_DO_DESTROY_MEMPOOL VALGRIND_DESTROY_MEMPOOL
66+
#define VALGRIND_DO_MEMPOOL_ALLOC VALGRIND_MEMPOOL_ALLOC
67+
#define VALGRIND_DO_MEMPOOL_FREE VALGRIND_MEMPOOL_FREE
68+
#else
69+
#define VALGRIND_DO_MALLOCLIKE_BLOCK(ptr, size, rzB, is_zeroed) \
70+
do { \
71+
(void)(ptr); \
72+
(void)(size); \
73+
(void)(rzB); \
74+
(void)(is_zeroed); \
75+
} while (0)
76+
77+
#define VALGRIND_DO_FREELIKE_BLOCK(ptr, rzB) \
78+
do { \
79+
(void)(ptr); \
80+
(void)(rzB); \
81+
} while (0)
82+
83+
#define VALGRIND_DO_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
84+
do { \
85+
(void)(pool); \
86+
(void)(rzB); \
87+
(void)(is_zeroed); \
88+
} while (0)
89+
90+
#define VALGRIND_DO_DESTROY_MEMPOOL(pool) \
91+
do { \
92+
(void)(pool); \
93+
} while (0)
94+
95+
#define VALGRIND_DO_MEMPOOL_ALLOC(pool, ptr, size) \
96+
do { \
97+
(void)(pool); \
98+
(void)(ptr); \
99+
(void)(size); \
100+
} while (0)
101+
102+
#define VALGRIND_DO_MEMPOOL_FREE(pool, ptr) \
103+
do { \
104+
(void)(pool); \
105+
(void)(ptr); \
106+
} while (0)
107+
#endif
108+
109+
#include <stdlib.h>
110+
22111
#ifdef __cplusplus
23112
extern "C" {
24113
#endif
25114

26-
void utils_annotate_acquire(void *ptr) {
115+
static inline void utils_annotate_acquire(void *ptr) {
27116
#if __SANITIZE_THREAD__
28117
__tsan_acquire(ptr);
29118
#else
30119
(void)ptr;
31120
#endif
32121
}
33122

34-
void utils_annotate_release(void *ptr) {
123+
static inline void utils_annotate_release(void *ptr) {
35124
#if __SANITIZE_THREAD__
36125
__tsan_release(ptr);
37126
#else
38127
(void)ptr;
39128
#endif
40129
}
41130

131+
// mark memory as accessible, defined
132+
static inline void utils_annotate_memory_defined(void *ptr, size_t size) {
133+
#ifdef __SANITIZE_ADDRESS__
134+
__asan_unpoison_memory_region(ptr, size);
135+
#elif UMF_VG_MEMCHECK_ENABLED
136+
VALGRIND_MAKE_MEM_DEFINED(ptr, size);
137+
#else
138+
(void)ptr;
139+
(void)size;
140+
#endif
141+
}
142+
143+
// mark memory as accessible, undefined
144+
static inline void utils_annotate_memory_undefined(void *ptr, size_t size) {
145+
#ifdef __SANITIZE_ADDRESS__
146+
__asan_unpoison_memory_region(ptr, size);
147+
#elif UMF_VG_MEMCHECK_ENABLED
148+
VALGRIND_MAKE_MEM_UNDEFINED(ptr, size);
149+
#else
150+
(void)ptr;
151+
(void)size;
152+
#endif
153+
}
154+
155+
static inline void utils_annotate_memory_inaccessible(void *ptr, size_t size) {
156+
#ifdef __SANITIZE_ADDRESS__
157+
__asan_poison_memory_region(ptr, size);
158+
#elif UMF_VG_MEMCHECK_ENABLED
159+
VALGRIND_MAKE_MEM_NOACCESS(ptr, size);
160+
#else
161+
(void)ptr;
162+
(void)size;
163+
#endif
164+
}
165+
42166
#ifdef __cplusplus
43167
}
44168
#endif

0 commit comments

Comments
 (0)