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