Home | History | Annotate | Download | only in docs
      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