1 ================ 2 MemorySanitizer 3 ================ 4 5 .. contents:: 6 :local: 7 8 Introduction 9 ============ 10 11 MemorySanitizer is a detector of uninitialized reads. It consists of a 12 compiler instrumentation module and a run-time library. 13 14 Typical slowdown introduced by MemorySanitizer is **3x**. 15 16 How to build 17 ============ 18 19 Build LLVM/Clang with `CMake <http://llvm.org/docs/CMake.html>`_. 20 21 Usage 22 ===== 23 24 Simply compile and link your program with ``-fsanitize=memory`` flag. 25 The MemorySanitizer run-time library should be linked to the final 26 executable, so make sure to use ``clang`` (not ``ld``) for the final 27 link step. When linking shared libraries, the MemorySanitizer run-time 28 is not linked, so ``-Wl,-z,defs`` may cause link errors (don't use it 29 with MemorySanitizer). To get a reasonable performance add ``-O1`` or 30 higher. To get meaninful stack traces in error messages add 31 ``-fno-omit-frame-pointer``. To get perfect stack traces you may need 32 to disable inlining (just use ``-O1``) and tail call elimination 33 (``-fno-optimize-sibling-calls``). 34 35 .. code-block:: console 36 37 % cat umr.cc 38 #include <stdio.h> 39 40 int main(int argc, char** argv) { 41 int* a = new int[10]; 42 a[5] = 0; 43 if (a[argc]) 44 printf("xx\n"); 45 return 0; 46 } 47 48 % clang -fsanitize=memory -fno-omit-frame-pointer -g -O2 umr.cc 49 50 If a bug is detected, the program will print an error message to 51 stderr and exit with a non-zero exit code. 52 53 .. code-block:: console 54 55 % ./a.out 56 WARNING: MemorySanitizer: use-of-uninitialized-value 57 #0 0x7f45944b418a in main umr.cc:6 58 #1 0x7f45938b676c in __libc_start_main libc-start.c:226 59 60 By default, MemorySanitizer exits on the first detected error. If you 61 find the error report hard to understand, try enabling 62 :ref:`origin tracking <msan-origins>`. 63 64 ``__has_feature(memory_sanitizer)`` 65 ------------------------------------ 66 67 In some cases one may need to execute different code depending on 68 whether MemorySanitizer is enabled. :ref:`\_\_has\_feature 69 <langext-__has_feature-__has_extension>` can be used for this purpose. 70 71 .. code-block:: c 72 73 #if defined(__has_feature) 74 # if __has_feature(memory_sanitizer) 75 // code that builds only under MemorySanitizer 76 # endif 77 #endif 78 79 ``__attribute__((no_sanitize_memory))`` 80 ----------------------------------------------- 81 82 Some code should not be checked by MemorySanitizer. One may use the function 83 attribute `no_sanitize_memory` to disable uninitialized checks in a particular 84 function. MemorySanitizer may still instrument such functions to avoid false 85 positives. This attribute may not be supported by other compilers, so we 86 suggest to use it together with ``__has_feature(memory_sanitizer)``. 87 88 Blacklist 89 --------- 90 91 MemorySanitizer supports ``src`` and ``fun`` entity types in 92 :doc:`SanitizerSpecialCaseList`, that can be used to relax MemorySanitizer 93 checks for certain source files and functions. All "Use of uninitialized value" 94 warnings will be suppressed and all values loaded from memory will be 95 considered fully initialized. 96 97 Report symbolization 98 ==================== 99 100 MemorySanitizer uses an external symbolizer to print files and line numbers in 101 reports. Make sure that ``llvm-symbolizer`` binary is in ``PATH``, 102 or set environment variable ``MSAN_SYMBOLIZER_PATH`` to point to it. 103 104 .. _msan-origins: 105 106 Origin Tracking 107 =============== 108 109 MemorySanitizer can track origins of uninitialized values, similar to 110 Valgrind's --track-origins option. This feature is enabled by 111 ``-fsanitize-memory-track-origins=2`` (or simply 112 ``-fsanitize-memory-track-origins``) Clang option. With the code from 113 the example above, 114 115 .. code-block:: console 116 117 % cat umr2.cc 118 #include <stdio.h> 119 120 int main(int argc, char** argv) { 121 int* a = new int[10]; 122 a[5] = 0; 123 volatile int b = a[argc]; 124 if (b) 125 printf("xx\n"); 126 return 0; 127 } 128 129 % clang -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g -O2 umr2.cc 130 % ./a.out 131 WARNING: MemorySanitizer: use-of-uninitialized-value 132 #0 0x7f7893912f0b in main umr2.cc:7 133 #1 0x7f789249b76c in __libc_start_main libc-start.c:226 134 135 Uninitialized value was stored to memory at 136 #0 0x7f78938b5c25 in __msan_chain_origin msan.cc:484 137 #1 0x7f7893912ecd in main umr2.cc:6 138 139 Uninitialized value was created by a heap allocation 140 #0 0x7f7893901cbd in operator new[](unsigned long) msan_new_delete.cc:44 141 #1 0x7f7893912e06 in main umr2.cc:4 142 143 By default, MemorySanitizer collects both allocation points and all 144 intermediate stores the uninitialized value went through. Origin 145 tracking has proved to be very useful for debugging MemorySanitizer 146 reports. It slows down program execution by a factor of 1.5x-2x on top 147 of the usual MemorySanitizer slowdown and increases memory overhead. 148 149 Clang option ``-fsanitize-memory-track-origins=1`` enables a slightly 150 faster mode when MemorySanitizer collects only allocation points but 151 not intermediate stores. 152 153 Use-after-destruction detection 154 =============================== 155 156 You can enable experimental use-after-destruction detection in MemorySanitizer. 157 After invocation of the destructor, the object will be considered no longer 158 readable, and using underlying memory will lead to error reports in runtime. 159 160 This feature is still experimental, in order to enable it at runtime you need 161 to: 162 163 #. Pass addition Clang option ``-fsanitize-memory-use-after-dtor`` during 164 compilation. 165 #. Set environment variable `MSAN_OPTIONS=poison_in_dtor=1` before running 166 the program. 167 168 Handling external code 169 ====================== 170 171 MemorySanitizer requires that all program code is instrumented. This 172 also includes any libraries that the program depends on, even libc. 173 Failing to achieve this may result in false reports. 174 For the same reason you may need to replace all inline assembly code that writes to memory 175 with a pure C/C++ code. 176 177 Full MemorySanitizer instrumentation is very difficult to achieve. To 178 make it easier, MemorySanitizer runtime library includes 70+ 179 interceptors for the most common libc functions. They make it possible 180 to run MemorySanitizer-instrumented programs linked with 181 uninstrumented libc. For example, the authors were able to bootstrap 182 MemorySanitizer-instrumented Clang compiler by linking it with 183 self-built instrumented libc++ (as a replacement for libstdc++). 184 185 Supported Platforms 186 =================== 187 188 MemorySanitizer is supported on Linux x86\_64/MIPS64/AArch64. 189 190 Limitations 191 =========== 192 193 * MemorySanitizer uses 2x more real memory than a native run, 3x with 194 origin tracking. 195 * MemorySanitizer maps (but not reserves) 64 Terabytes of virtual 196 address space. This means that tools like ``ulimit`` may not work as 197 usually expected. 198 * Static linking is not supported. 199 * Older versions of MSan (LLVM 3.7 and older) didn't work with 200 non-position-independent executables, and could fail on some Linux 201 kernel versions with disabled ASLR. Refer to documentation for older versions 202 for more details. 203 204 Current Status 205 ============== 206 207 MemorySanitizer is known to work on large real-world programs 208 (like Clang/LLVM itself) that can be recompiled from source, including all 209 dependent libraries. 210 211 More Information 212 ================ 213 214 `<https://github.com/google/sanitizers/wiki/MemorySanitizer>`_ 215