| 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 | 
| Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 19 |  | 
|  | 20 | Typical slowdown introduced by AddressSanitizer is **2x**. | 
|  | 21 |  | 
|  | 22 | How to build | 
|  | 23 | ============ | 
|  | 24 |  | 
| Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 25 | Follow the `clang build instructions <../get_started.html>`_. CMake build is | 
|  | 26 | supported. | 
| 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 | 
|  | 63 | exit with a non-zero exit code. Currently, AddressSanitizer does not symbolize | 
|  | 64 | its output, so you may need to use a separate script to symbolize the result | 
|  | 65 | offline (this will be fixed in future). | 
| Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 66 |  | 
| Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 67 | .. code-block:: console | 
| Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 68 |  | 
|  | 69 | % ./a.out 2> log | 
|  | 70 | % projects/compiler-rt/lib/asan/scripts/asan_symbolize.py / < log | c++filt | 
|  | 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 |  | 
|  | 86 | AddressSanitizer exits on the first detected error. This is by design. | 
|  | 87 | One reason: it makes the generated code smaller and faster (both by | 
|  | 88 | ~5%). Another reason: this makes fixing bugs unavoidable. With Valgrind, | 
|  | 89 | it is often the case that users treat Valgrind warnings as false | 
|  | 90 | positives (which they are not) and don't fix them. | 
|  | 91 |  | 
| Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 92 | ``__has_feature(address_sanitizer)`` | 
| Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 93 | ------------------------------------ | 
|  | 94 |  | 
| Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 95 | In some cases one may need to execute different code depending on whether | 
|  | 96 | AddressSanitizer is enabled. | 
|  | 97 | :ref:`\_\_has\_feature <langext-__has_feature-__has_extension>` can be used for | 
|  | 98 | this purpose. | 
| Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 99 |  | 
| Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 100 | .. code-block:: c | 
| Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 101 |  | 
|  | 102 | #if defined(__has_feature) | 
| Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 103 | #  if __has_feature(address_sanitizer) | 
|  | 104 | // code that builds only under AddressSanitizer | 
|  | 105 | #  endif | 
| Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 106 | #endif | 
|  | 107 |  | 
| Kostya Serebryany | 85aee96 | 2013-02-26 06:58:27 +0000 | [diff] [blame] | 108 | ``__attribute__((no_sanitize_address))`` | 
| Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 109 | ----------------------------------------------- | 
| Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 110 |  | 
| Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 111 | Some code should not be instrumented by AddressSanitizer. One may use the | 
|  | 112 | function attribute | 
| Kostya Serebryany | 85aee96 | 2013-02-26 06:58:27 +0000 | [diff] [blame] | 113 | :ref:`no_sanitize_address <langext-address_sanitizer>` | 
|  | 114 | (or a deprecated synonym `no_address_safety_analysis`) | 
| Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 115 | to disable instrumentation of a particular function. This attribute may not be | 
|  | 116 | supported by other compilers, so we suggest to use it together with | 
| Evgeniy Stepanov | fa203cf | 2013-08-15 13:57:11 +0000 | [diff] [blame^] | 117 | ``__has_feature(address_sanitizer)``. | 
| Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 118 |  | 
| Dmitri Gribenko | 23219da | 2013-03-14 12:53:46 +0000 | [diff] [blame] | 119 | Initialization order checking | 
|  | 120 | ----------------------------- | 
| Alexey Samsonov | f37b1e2 | 2013-03-14 12:26:21 +0000 | [diff] [blame] | 121 |  | 
|  | 122 | AddressSanitizer can optionally detect dynamic initialization order problems, | 
|  | 123 | when initialization of globals defined in one translation unit uses | 
|  | 124 | globals defined in another translation unit. To enable this check at runtime, | 
|  | 125 | you should set environment variable | 
|  | 126 | ``ASAN_OPTIONS=check_initialization_order=1``. | 
| Dmitri Gribenko | 23219da | 2013-03-14 12:53:46 +0000 | [diff] [blame] | 127 |  | 
| Alexey Samsonov | 05654ff | 2013-08-07 08:23:32 +0000 | [diff] [blame] | 128 | Blacklist | 
|  | 129 | --------- | 
|  | 130 |  | 
|  | 131 | AddressSanitizer supports ``src`` and ``fun`` entity types in | 
|  | 132 | :doc:`SanitizerSpecialCaseList`, that can be used to suppress error reports | 
|  | 133 | in the specified source files or functions. Additionally, AddressSanitizer | 
|  | 134 | introduces ``global`` and ``type`` entity types that can be used to | 
|  | 135 | suppress error reports for out-of-bound access to globals with certain | 
|  | 136 | names and types (you may only specify class or struct types). | 
|  | 137 |  | 
|  | 138 | You may use an ``init`` category to suppress reports about initialization-order | 
|  | 139 | problems happening in certain source files or with certain global variables. | 
|  | 140 |  | 
|  | 141 | .. code-block:: bash | 
|  | 142 |  | 
|  | 143 | # Suppress error reports for code in a file or in a function: | 
|  | 144 | src:bad_file.cpp | 
|  | 145 | # Ignore all functions with names containing MyFooBar: | 
|  | 146 | fun:*MyFooBar* | 
|  | 147 | # Disable out-of-bound checks for global: | 
|  | 148 | global:bad_array | 
|  | 149 | # Disable out-of-bound checks for global instances of a given class ... | 
|  | 150 | type:class.Namespace::BadClassName | 
|  | 151 | # ... or a given struct. Use wildcard to deal with anonymous namespace. | 
|  | 152 | type:struct.Namespace2::*::BadStructName | 
|  | 153 | # Disable initialization-order checks for globals: | 
|  | 154 | global:bad_init_global=init | 
|  | 155 | type:*BadInitClassSubstring*=init | 
|  | 156 | src:bad/init/files/*=init | 
|  | 157 |  | 
| Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 158 | Supported Platforms | 
|  | 159 | =================== | 
|  | 160 |  | 
|  | 161 | AddressSanitizer is supported on | 
|  | 162 |  | 
| Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 163 | * Linux i386/x86\_64 (tested on Ubuntu 10.04 and 12.04); | 
| Alexey Samsonov | e6a0f09 | 2013-07-19 12:53:04 +0000 | [diff] [blame] | 164 | * MacOS 10.6, 10.7 and 10.8 (i386/x86\_64). | 
| Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 165 |  | 
|  | 166 | Support for Linux ARM (and Android ARM) is in progress (it may work, but | 
|  | 167 | is not guaranteed too). | 
|  | 168 |  | 
|  | 169 | Limitations | 
|  | 170 | =========== | 
|  | 171 |  | 
| Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 172 | * AddressSanitizer uses more real memory than a native run. Exact overhead | 
|  | 173 | depends on the allocations sizes. The smaller the allocations you make the | 
|  | 174 | bigger the overhead is. | 
|  | 175 | * AddressSanitizer uses more stack memory. We have seen up to 3x increase. | 
|  | 176 | * On 64-bit platforms AddressSanitizer maps (but not reserves) 16+ Terabytes of | 
|  | 177 | virtual address space. This means that tools like ``ulimit`` may not work as | 
|  | 178 | usually expected. | 
|  | 179 | * Static linking is not supported. | 
| Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 180 |  | 
|  | 181 | Current Status | 
|  | 182 | ============== | 
|  | 183 |  | 
| Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 184 | AddressSanitizer is fully functional on supported platforms starting from LLVM | 
|  | 185 | 3.1. The test suite is integrated into CMake build and can be run with ``make | 
|  | 186 | check-asan`` command. | 
| Sean Silva | 93ca021 | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 187 |  | 
|  | 188 | More Information | 
|  | 189 | ================ | 
|  | 190 |  | 
| Dmitri Gribenko | 97555a1 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 191 | `http://code.google.com/p/address-sanitizer <http://code.google.com/p/address-sanitizer/>`_ | 
|  | 192 |  |