Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 1 | ================ |
| 2 | AddressSanitizer |
| 3 | ================ |
| 4 | |
| 5 | .. contents:: |
| 6 | :local: |
| 7 | |
| 8 | Introduction |
| 9 | ============ |
| 10 | |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 11 | AddressSanitizer is a fast memory error detector. It consists of a compiler |
| 12 | instrumentation module and a run-time library. The tool can detect the |
| 13 | following types of bugs: |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 14 | |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 15 | * Out-of-bounds accesses to heap, stack and globals |
| 16 | * Use-after-free |
| 17 | * Use-after-return (to some extent) |
| 18 | * Double-free, invalid free |
Sergey Matveev | ceab8e2 | 2013-12-11 09:15:45 +0000 | [diff] [blame] | 19 | * Memory leaks (experimental) |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 20 | |
| 21 | Typical slowdown introduced by AddressSanitizer is **2x**. |
| 22 | |
| 23 | How to build |
| 24 | ============ |
| 25 | |
Stephen Hines | 0e2c34f | 2015-03-23 12:09:02 -0700 | [diff] [blame^] | 26 | Build LLVM/Clang with `CMake <http://llvm.org/docs/CMake.html>`_. |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 27 | |
| 28 | Usage |
| 29 | ===== |
| 30 | |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 31 | Simply compile and link your program with ``-fsanitize=address`` flag. The |
| 32 | AddressSanitizer run-time library should be linked to the final executable, so |
| 33 | make sure to use ``clang`` (not ``ld``) for the final link step. When linking |
| 34 | shared libraries, the AddressSanitizer run-time is not linked, so |
| 35 | ``-Wl,-z,defs`` may cause link errors (don't use it with AddressSanitizer). To |
| 36 | get a reasonable performance add ``-O1`` or higher. To get nicer stack traces |
| 37 | in error messages add ``-fno-omit-frame-pointer``. To get perfect stack traces |
| 38 | you may need to disable inlining (just use ``-O1``) and tail call elimination |
| 39 | (``-fno-optimize-sibling-calls``). |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 40 | |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 41 | .. code-block:: console |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 42 | |
| 43 | % cat example_UseAfterFree.cc |
| 44 | int main(int argc, char **argv) { |
| 45 | int *array = new int[100]; |
| 46 | delete [] array; |
| 47 | return array[argc]; // BOOM |
| 48 | } |
| 49 | |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 50 | # Compile and link |
| 51 | % clang -O1 -g -fsanitize=address -fno-omit-frame-pointer example_UseAfterFree.cc |
| 52 | |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 53 | or: |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 54 | |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 55 | .. code-block:: console |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 56 | |
| 57 | # Compile |
| 58 | % clang -O1 -g -fsanitize=address -fno-omit-frame-pointer -c example_UseAfterFree.cc |
| 59 | # Link |
| 60 | % clang -g -fsanitize=address example_UseAfterFree.o |
| 61 | |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 62 | If a bug is detected, the program will print an error message to stderr and |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 63 | exit with a non-zero exit code. To make AddressSanitizer symbolize its output |
| 64 | you need to set the ``ASAN_SYMBOLIZER_PATH`` environment variable to point to |
| 65 | the ``llvm-symbolizer`` binary (or make sure ``llvm-symbolizer`` is in your |
| 66 | ``$PATH``): |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 67 | |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 68 | .. code-block:: console |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 69 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 70 | % ASAN_SYMBOLIZER_PATH=/usr/local/bin/llvm-symbolizer ./a.out |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 71 | ==9442== ERROR: AddressSanitizer heap-use-after-free on address 0x7f7ddab8c084 at pc 0x403c8c bp 0x7fff87fb82d0 sp 0x7fff87fb82c8 |
| 72 | READ of size 4 at 0x7f7ddab8c084 thread T0 |
| 73 | #0 0x403c8c in main example_UseAfterFree.cc:4 |
| 74 | #1 0x7f7ddabcac4d in __libc_start_main ??:0 |
| 75 | 0x7f7ddab8c084 is located 4 bytes inside of 400-byte region [0x7f7ddab8c080,0x7f7ddab8c210) |
| 76 | freed by thread T0 here: |
| 77 | #0 0x404704 in operator delete[](void*) ??:0 |
| 78 | #1 0x403c53 in main example_UseAfterFree.cc:4 |
| 79 | #2 0x7f7ddabcac4d in __libc_start_main ??:0 |
| 80 | previously allocated by thread T0 here: |
| 81 | #0 0x404544 in operator new[](unsigned long) ??:0 |
| 82 | #1 0x403c43 in main example_UseAfterFree.cc:2 |
| 83 | #2 0x7f7ddabcac4d in __libc_start_main ??:0 |
| 84 | ==9442== ABORTING |
| 85 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 86 | If that does not work for you (e.g. your process is sandboxed), you can use a |
| 87 | separate script to symbolize the result offline (online symbolization can be |
| 88 | force disabled by setting ``ASAN_OPTIONS=symbolize=0``): |
| 89 | |
| 90 | .. code-block:: console |
| 91 | |
| 92 | % ASAN_OPTIONS=symbolize=0 ./a.out 2> log |
| 93 | % projects/compiler-rt/lib/asan/scripts/asan_symbolize.py / < log | c++filt |
| 94 | ==9442== ERROR: AddressSanitizer heap-use-after-free on address 0x7f7ddab8c084 at pc 0x403c8c bp 0x7fff87fb82d0 sp 0x7fff87fb82c8 |
| 95 | READ of size 4 at 0x7f7ddab8c084 thread T0 |
| 96 | #0 0x403c8c in main example_UseAfterFree.cc:4 |
| 97 | #1 0x7f7ddabcac4d in __libc_start_main ??:0 |
| 98 | ... |
| 99 | |
| 100 | Note that on OS X you may need to run ``dsymutil`` on your binary to have the |
| 101 | file\:line info in the AddressSanitizer reports. |
| 102 | |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 103 | AddressSanitizer exits on the first detected error. This is by design. |
| 104 | One reason: it makes the generated code smaller and faster (both by |
| 105 | ~5%). Another reason: this makes fixing bugs unavoidable. With Valgrind, |
| 106 | it is often the case that users treat Valgrind warnings as false |
| 107 | positives (which they are not) and don't fix them. |
| 108 | |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 109 | ``__has_feature(address_sanitizer)`` |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 110 | ------------------------------------ |
| 111 | |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 112 | In some cases one may need to execute different code depending on whether |
| 113 | AddressSanitizer is enabled. |
| 114 | :ref:`\_\_has\_feature <langext-__has_feature-__has_extension>` can be used for |
| 115 | this purpose. |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 116 | |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 117 | .. code-block:: c |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 118 | |
| 119 | #if defined(__has_feature) |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 120 | # if __has_feature(address_sanitizer) |
| 121 | // code that builds only under AddressSanitizer |
| 122 | # endif |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 123 | #endif |
| 124 | |
Kostya Serebryany | 85aee96 | 2013-02-26 06:58:27 +0000 | [diff] [blame] | 125 | ``__attribute__((no_sanitize_address))`` |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 126 | ----------------------------------------------- |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 127 | |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 128 | Some code should not be instrumented by AddressSanitizer. One may use the |
| 129 | function attribute |
Kostya Serebryany | 85aee96 | 2013-02-26 06:58:27 +0000 | [diff] [blame] | 130 | :ref:`no_sanitize_address <langext-address_sanitizer>` |
| 131 | (or a deprecated synonym `no_address_safety_analysis`) |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 132 | to disable instrumentation of a particular function. This attribute may not be |
| 133 | supported by other compilers, so we suggest to use it together with |
Evgeniy Stepanov | fa203cf | 2013-08-15 13:57:11 +0000 | [diff] [blame] | 134 | ``__has_feature(address_sanitizer)``. |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 135 | |
Dmitri Gribenko | 23219da | 2013-03-14 12:53:46 +0000 | [diff] [blame] | 136 | Initialization order checking |
| 137 | ----------------------------- |
Alexey Samsonov | f37b1e2 | 2013-03-14 12:26:21 +0000 | [diff] [blame] | 138 | |
| 139 | AddressSanitizer can optionally detect dynamic initialization order problems, |
| 140 | when initialization of globals defined in one translation unit uses |
| 141 | globals defined in another translation unit. To enable this check at runtime, |
| 142 | you should set environment variable |
| 143 | ``ASAN_OPTIONS=check_initialization_order=1``. |
Dmitri Gribenko | 23219da | 2013-03-14 12:53:46 +0000 | [diff] [blame] | 144 | |
Alexey Samsonov | 05654ff | 2013-08-07 08:23:32 +0000 | [diff] [blame] | 145 | Blacklist |
| 146 | --------- |
| 147 | |
| 148 | AddressSanitizer supports ``src`` and ``fun`` entity types in |
| 149 | :doc:`SanitizerSpecialCaseList`, that can be used to suppress error reports |
| 150 | in the specified source files or functions. Additionally, AddressSanitizer |
| 151 | introduces ``global`` and ``type`` entity types that can be used to |
| 152 | suppress error reports for out-of-bound access to globals with certain |
| 153 | names and types (you may only specify class or struct types). |
| 154 | |
| 155 | You may use an ``init`` category to suppress reports about initialization-order |
| 156 | problems happening in certain source files or with certain global variables. |
| 157 | |
| 158 | .. code-block:: bash |
| 159 | |
| 160 | # Suppress error reports for code in a file or in a function: |
| 161 | src:bad_file.cpp |
| 162 | # Ignore all functions with names containing MyFooBar: |
| 163 | fun:*MyFooBar* |
| 164 | # Disable out-of-bound checks for global: |
| 165 | global:bad_array |
| 166 | # Disable out-of-bound checks for global instances of a given class ... |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 167 | type:Namespace::BadClassName |
Alexey Samsonov | 05654ff | 2013-08-07 08:23:32 +0000 | [diff] [blame] | 168 | # ... or a given struct. Use wildcard to deal with anonymous namespace. |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 169 | type:Namespace2::*::BadStructName |
Alexey Samsonov | 05654ff | 2013-08-07 08:23:32 +0000 | [diff] [blame] | 170 | # Disable initialization-order checks for globals: |
| 171 | global:bad_init_global=init |
| 172 | type:*BadInitClassSubstring*=init |
| 173 | src:bad/init/files/*=init |
| 174 | |
Sergey Matveev | ceab8e2 | 2013-12-11 09:15:45 +0000 | [diff] [blame] | 175 | Memory leak detection |
| 176 | --------------------- |
| 177 | |
| 178 | For the experimental memory leak detector in AddressSanitizer, see |
| 179 | :doc:`LeakSanitizer`. |
| 180 | |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 181 | Supported Platforms |
| 182 | =================== |
| 183 | |
| 184 | AddressSanitizer is supported on |
| 185 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 186 | * Linux i386/x86\_64 (tested on Ubuntu 12.04); |
| 187 | * MacOS 10.6 - 10.9 (i386/x86\_64). |
| 188 | * Android ARM |
Stephen Hines | 0e2c34f | 2015-03-23 12:09:02 -0700 | [diff] [blame^] | 189 | * FreeBSD i386/x86\_64 (tested on FreeBSD 11-current) |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 190 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 191 | Ports to various other platforms are in progress. |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 192 | |
| 193 | Limitations |
| 194 | =========== |
| 195 | |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 196 | * AddressSanitizer uses more real memory than a native run. Exact overhead |
| 197 | depends on the allocations sizes. The smaller the allocations you make the |
| 198 | bigger the overhead is. |
| 199 | * AddressSanitizer uses more stack memory. We have seen up to 3x increase. |
| 200 | * On 64-bit platforms AddressSanitizer maps (but not reserves) 16+ Terabytes of |
| 201 | virtual address space. This means that tools like ``ulimit`` may not work as |
| 202 | usually expected. |
| 203 | * Static linking is not supported. |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 204 | |
| 205 | Current Status |
| 206 | ============== |
| 207 | |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 208 | AddressSanitizer is fully functional on supported platforms starting from LLVM |
| 209 | 3.1. The test suite is integrated into CMake build and can be run with ``make |
| 210 | check-asan`` command. |
Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 211 | |
| 212 | More Information |
| 213 | ================ |
| 214 | |
Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 215 | `http://code.google.com/p/address-sanitizer <http://code.google.com/p/address-sanitizer/>`_ |
| 216 | |