Home | History | Annotate | Download | only in debug
      1 page.title=AddressSanitizer
      2 @jd:body
      3 
      4 <!--
      5     Copyright 2015 The Android Open Source Project
      6 
      7     Licensed under the Apache License, Version 2.0 (the "License");
      8     you may not use this file except in compliance with the License.
      9     You may obtain a copy of the License at
     10 
     11         http://www.apache.org/licenses/LICENSE-2.0
     12 
     13     Unless required by applicable law or agreed to in writing, software
     14     distributed under the License is distributed on an "AS IS" BASIS,
     15     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16     See the License for the specific language governing permissions and
     17     limitations under the License.
     18 -->
     19 <div id="qv-wrapper">
     20   <div id="qv">
     21     <h2>In this document</h2>
     22     <ol id="auto-toc">
     23     </ol>
     24   </div>
     25 </div>
     26 
     27 <h2 id=purpose>Purpose</h2>
     28 
     29 <p>AddressSanitizer (ASan) is a fast compiler-based tool for detecting memory bugs
     30 in native code. It is comparable to Valgrind (Memcheck tool), but, unlike it,
     31 ASan:</p>
     32 
     33 <ul>
     34   <li> + detects overflows on stack and global objects
     35   <li> - does not detect uninitialized reads and memory leaks
     36   <li> + is much faster (two-three times slowdown compared to Valgrinds 20-100x)
     37   <li> + has less memory overhead
     38 </ul>
     39 
     40 <p>This document describes how to build and run parts of the Android platform with
     41 AddressSanitizer. If you are looking to build a standalone (i.e. SDK/NDK)
     42 application with AddressSanitizer, see the <a
     43 href="https://github.com/google/sanitizers/wiki/AddressSanitizerOnAndroid">AddressSanitizerOnAndroid</a>
     44 public project site instead.</p>
     45 
     46 <p>AddressSanitizer consists of a compiler (<code>external/clang</code>) and a runtime library
     47 (<code>external/compiler-rt/lib/asan</code>).</p>
     48 
     49 <p class="note"><strong>Note</strong>: Use the current master
     50 branch to gain access to the <a href="#sanitize_target">SANITIZE_TARGET</a>
     51 feature and the ability to build the entire Android platform with
     52 AddressSanitizer at once. Otherwise, you are limited to using
     53 <code>LOCAL_SANITIZE</code>.</p>
     54 
     55 <h2 id=building_with_clang>Building with Clang</h2>
     56 
     57 <p>As a first step to building an ASan-instrumented binary, make sure that your
     58 code builds with Clang. This is done by adding <code>LOCAL_CLANG:=true</code>
     59 to the build rules. Clang may find bugs in your code that GCC missed.</p>
     60 
     61 <h2 id=building_executables_with_addresssanitizer>Building executables with AddressSanitizer</h2>
     62 
     63 <p>Add <code>LOCAL_SANITIZE:=address</code> to the build rule of the
     64 executable. This requires: <code>LOCAL_CLANG:=true</code></p>
     65 
     66 <pre>
     67 LOCAL_CLANG:=true
     68 LOCAL_SANITIZE:=address
     69 </pre>
     70 
     71 <p>When a bug is detected, ASan prints a verbose report both to the standard
     72 output and to <code>logcat</code> and then crashes the process.</p>
     73 
     74 <h2 id=building_shared_libraries_with_addresssanitizer>Building shared libraries with AddressSanitizer</h2>
     75 
     76 <p>Due to the way ASan works, a library built with ASan cannot be used by an
     77 executable that's built without ASan.</p>
     78 
     79 <p class="note">Note</strong>: In runtime situations where an ASan library is
     80 loaded into an incorrect process, you will see unresolved symbol messages
     81 starting with <code>_asan</code> or <code>_sanitizer</code>.</p>
     82 
     83 <p>To sanitize a shared library that is used in multiple executables, not all of
     84 which are built with ASan, you'll need two copies of the library. The
     85 recommended way to do this is to add the following to <code>Android.mk</code>
     86 for the module in question:</p>
     87 
     88 <pre>
     89 LOCAL_CLANG:=true
     90 LOCAL_SANITIZE:=address
     91 LOCAL_MODULE_RELATIVE_PATH := asan
     92 </pre>
     93 
     94 <p>This puts the library in <code>/system/lib/asan</code> instead of
     95 <code>/system/lib</code>. Then, run your executable with:
     96 <code>LD_LIBRARY_PATH=/system/lib/asan</code></p>
     97 
     98 <p>For system daemons, add the following to the appropriate section of
     99 <code>/init.rc</code> or <code>/init.$device$.rc</code>.</p>
    100 
    101 <pre>
    102 setenv LD_LIBRARY_PATH /system/lib/asan
    103 </pre>
    104 
    105 <p class="warning"><strong>Warning</strong>: The <code>LOCAL_MODULE_RELATIVE_PATH</code>
    106 setting <strong>moves</strong> your library to <code>/system/lib/asan</code>,
    107 meaning that clobbering and rebuilding from scratch will result in the
    108 library missing from <code>/system/lib</code>, and probably an unbootable
    109 image. That's an unfortunate limitation of the
    110 current build system. Don't clobber; do <code>make -j $N</code> and <code>adb
    111 sync</code>.</p>
    112 
    113 <p>Verify the process is using libraries from <code>/system/lib/asan</code>
    114 when present by reading <code>/proc/$PID/maps</code>. If it's not, you may need
    115 to disable SELinux, like so:</p>
    116 
    117 <pre>
    118 $ adb root
    119 $ adb shell setenforce 0
    120 # restart the process with adb shell kill $PID
    121 # if it is a system service, or may be adb shell stop; adb shell start.
    122 </pre>
    123 
    124 <h2 id=better_stack_traces>Better stack traces</h2>
    125 
    126 <p>AddressSanitizer uses a fast, frame-pointer-based unwinder to record a stack
    127 trace for every memory allocation and deallocation event in the program. Most
    128 of Android is built without frame pointers. As a result, you will often get
    129 only one or two meaningful frames. To fix this, either rebuild the library with
    130 ASan (recommended!), or with:</p>
    131 
    132 <pre>
    133 LOCAL_CFLAGS:=-fno-omit-frame-pointer
    134 LOCAL_ARM_MODE:=arm
    135 </pre>
    136 
    137 <p>Or set <code>ASAN_OPTIONS=fast_unwind_on_malloc=0</code> in the process
    138 environment. The latter can be very CPU-intensive, depending on
    139 the load.</p>
    140 
    141 <h2 id=symbolization>Symbolization</h2>
    142 
    143 <p>Initially, ASan reports contain references to offsets in binaries and shared
    144 libraries. There are two ways to obtain source file and line information:</p>
    145 
    146 <ul>
    147   <li>Ensure llvm-symbolizer binary is present in <code>/system/bin</code>.
    148 Llvm-symbolizer is built from sources in:
    149 <code>third_party/llvm/tools/llvm-symbolizer</code> <li>Filter the report
    150 through the <code>external/compiler-rt/lib/asan/scripts/symbolize.py</code>
    151 script.
    152 </ul>
    153 
    154 <p>The second approach can provide more data (i.e. file:line locations) because of
    155 the availability of symbolized libraries on the host.</p>
    156 
    157 <h2 id=addresssanitizer_in_the_apps>AddressSanitizer in the apps</h2>
    158 
    159 <p>AddressSanitizer cannot see into Java code, but it can detect bugs in the JNI
    160 libraries. For that, you'll need to build the executable with ASan, which in
    161 this case is <code>/system/bin/app_process(<em>32|64</code></em>). This will
    162 enable ASan in all apps on the device at the same time, which is a
    163 bit stressful, but nothing that a 2GB RAM device cannot handle.</p>
    164 
    165 <p>Add the usual <code>LOCAL_CLANG:=true, LOCAL_SANITIZE:=address</code> to
    166 the app_process build rule in <code>frameworks/base/cmds/app_process</code>. Ignore
    167 the <code>app_process__asan</code> target in the same file for now (if it is
    168 still there at the time you read
    169 this). Edit the Zygote record in
    170 <code>system/core/rootdir/init.zygote(<em>32|64</em>).rc</code> to add the
    171 following lines:</p>
    172 
    173 <pre>
    174 setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib
    175 setenv ASAN_OPTIONS
    176 allow_user_segv_handler=true
    177 </pre>
    178 
    179 <p>Build, adb sync, fastboot flash boot, reboot.</p>
    180 
    181 <h2 id=using_the_wrap_property>Using the wrap property</h2>
    182 
    183 <p>The approach in the previous section puts AddressSanitizer into every
    184 application in the system (actually, into every descendant of the Zygote
    185 process). It is possible to run only one (or several) applications with ASan,
    186 trading some memory overhead for slower application startup.</p>
    187 
    188 <p>This can be done by starting your app with the wrap. property, the same one
    189 thats used to run apps under Valgrind. The following example runs the Gmail app
    190 under ASan:</p>
    191 
    192 <pre>
    193 $ adb root
    194 $ adb shell setenforce 0  # disable SELinux
    195 $ adb shell setprop wrap.com.google.android.gm "asanwrapper"
    196 </pre>
    197 
    198 <p>In this context, asanwrapper rewrites <code>/system/bin/app_process</code>
    199 to <code>/system/bin/asan/app_process</code>, which is built with
    200 AddressSanitizer. It also adds <code>/system/lib/asan</code> at the start of
    201 the dynamic library search path. This way ASan-instrumented
    202 libraries from <code>/system/lib/asan</code> are preferred to normal libraries
    203 in <code>/system/lib</code> when running with asanwrapper.</p>
    204 
    205 <p>Again, if a bug is found, the app will crash, and the report will be printed to
    206 the log.</p>
    207 
    208 <h2 id=sanitize_target>SANITIZE_TARGET</h2>
    209 
    210 <p>The master branch has support for building the entire Android platform with
    211 AddressSanitizer at once.</p>
    212 
    213 <p>Run the following commands in the same build tree.</p>
    214 
    215 <pre>
    216 $ make -j42
    217 $ make USE_CLANG_PLATFORM_BUILD:=true SANITIZE_TARGET=address -j42
    218 </pre>
    219 
    220 <p>In this mode, <code>userdata.img</code> contains extra libraries and must be
    221 flashed to the device as well. Use the following command line:</p>
    222 
    223 <pre>
    224 $ fastboot flash userdata && fastboot flashall
    225 </pre>
    226 
    227 <p>At the moment of this writing, hammerhead-userdebug and shamu-userdebug boot to
    228 the UI in this mode.</p>
    229 
    230 <p>This works by building two sets of shared libraries: normal in
    231 <code>/system/lib</code> (the first make invocation), ASan-instrumented in
    232 <code>/data/lib</code> (the second make invocation). Executables from the
    233 second build overwrite the ones from the first build. ASan-instrumented
    234 executables get a different library search path that includes
    235 <code>/data/lib</code> before <code>/system/lib</code> through the use of
    236 "/system/bin/linker_asan" in PT_INTERP.</p>
    237 
    238 <p>The build system clobbers intermediate object directories when the
    239 <code>$SANITIZE_TARGET</code> value has changed. This forces a rebuild of all
    240 targets while preserving installed binaries under <code>/system/lib</code>.</p>
    241 
    242 <p>Some targets cannot be built with ASan:</p>
    243 
    244 <ul>
    245   <li>Statically linked executables.
    246   <li><code>LOCAL_CLANG:=false</code> targets
    247   <li><code>LOCAL_SANITIZE:=undefined</code>; will not be ASan'd for <code>SANITIZE_TARGET=address</code>
    248 </ul>
    249 
    250 <p>Executables like these are skipped in the SANITIZE_TARGET build, and the
    251 version from the first make invocation is left in <code>/system/bin</code>.</p>
    252 
    253 <p>Libraries like this are simply built without ASan. They can contain some ASan
    254 code anyway from the static libraries they depend upon.</p>
    255 
    256 <h2 id=supporting_documentation>Supporting documentation</h2>
    257 
    258 <p><a href="https://github.com/google/sanitizers/wiki/AddressSanitizerOnAndroid">AddressSanitizerOnAndroid</a> public project site</p>
    259 <p><a href="https://www.chromium.org/developers/testing/addresssanitizer">AddressSanitizer and Chromium</a></p>
    260 <p><a href="https://github.com/google/sanitizers">Other Google Sanitizers</a></p>
    261