blob: 9b13a5ad9aed98429e0a05b2dc0c9c71bf342cc4 [file] [log] [blame]
Clay Murphyf0484332015-08-27 18:50:47 -07001page.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
30in native code. It is comparable to Valgrind (Memcheck tool), but, unlike it,
31ASan:</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
41AddressSanitizer. If you are looking to build a standalone (i.e. SDK/NDK)
42application with AddressSanitizer, see the <a
43href="https://github.com/google/sanitizers/wiki/AddressSanitizerOnAndroid">AddressSanitizerOnAndroid</a>
44public 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
50branch to gain access to the <a href="#sanitize_target">SANITIZE_TARGET</a>
51feature and the ability to build the entire Android platform with
52AddressSanitizer 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
58code builds with Clang. This is done by adding <code>LOCAL_CLANG:=true</code>
59to 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
64executable. This requires: <code>LOCAL_CLANG:=true</code></p>
65
66<pre>
67LOCAL_CLANG:=true
68LOCAL_SANITIZE:=address
69</pre>
70
71<p>When a bug is detected, ASan prints a verbose report both to the standard
72output 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
77executable that's built without ASan.</p>
78
79<p class="note">Note</strong>: In runtime situations where an ASan library is
80loaded into an incorrect process, you will see unresolved symbol messages
81starting 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
84which are built with ASan, you'll need two copies of the library. The
85recommended way to do this is to add the following to <code>Android.mk</code>
86for the module in question:</p>
87
88<pre>
89LOCAL_CLANG:=true
90LOCAL_SANITIZE:=address
91LOCAL_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>
102setenv LD_LIBRARY_PATH /system/lib/asan
103</pre>
104
105<p class="warning"><strong>Warning</strong>: The <code>LOCAL_MODULE_RELATIVE_PATH</code>
106setting <strong>moves</strong> your library to <code>/system/lib/asan</code>,
107meaning that clobbering and rebuilding from scratch will result in the
108library missing from <code>/system/lib</code>, and probably an unbootable
109image. That's an unfortunate limitation of the
110current build system. Don't clobber; do <code>make -j $N</code> and <code>adb
111sync</code>.</p>
112
113<p>Verify the process is using libraries from <code>/system/lib/asan</code>
114when present by reading <code>/proc/$PID/maps</code>. If it's not, you may need
115to 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
127trace for every memory allocation and deallocation event in the program. Most
128of Android is built without frame pointers. As a result, you will often get
129only one or two meaningful frames. To fix this, either rebuild the library with
130ASan (recommended!), or with:</p>
131
132<pre>
133LOCAL_CFLAGS:=-fno-omit-frame-pointer
134LOCAL_ARM_MODE:=arm
135</pre>
136
137<p>Or set <code>ASAN_OPTIONS=fast_unwind_on_malloc=0</code> in the process
138environment. The latter can be very CPU-intensive, depending on
139the load.</p>
140
141<h2 id=symbolization>Symbolization</h2>
142
143<p>Initially, ASan reports contain references to offsets in binaries and shared
144libraries. 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>.
148Llvm-symbolizer is built from sources in:
149<code>third_party/llvm/tools/llvm-symbolizer</code> <li>Filter the report
150through the <code>external/compiler-rt/lib/asan/scripts/symbolize.py</code>
151script.
152</ul>
153
154<p>The second approach can provide more data (i.e. file:line locations) because of
155the 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
160libraries. For that, you'll need to build the executable with ASan, which in
161this case is <code>/system/bin/app_process(<em>32|64</code></em>). This will
162enable ASan in all apps on the device at the same time, which is a
163bit 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
166the app_process build rule in <code>frameworks/base/cmds/app_process</code>. Ignore
167the <code>app_process__asan</code> target in the same file for now (if it is
168still there at the time you read
169this). Edit the Zygote record in
170<code>system/core/rootdir/init.zygote(<em>32|64</em>).rc</code> to add the
171following lines:</p>
172
173<pre>
174setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib
175setenv ASAN_OPTIONS
176allow_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
184application in the system (actually, into every descendant of the Zygote
185process). It is possible to run only one (or several) applications with ASan,
186trading 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
189thats used to run apps under Valgrind. The following example runs the Gmail app
190under 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>
199to <code>/system/bin/asan/app_process</code>, which is built with
200AddressSanitizer. It also adds <code>/system/lib/asan</code> at the start of
201the dynamic library search path. This way ASan-instrumented
202libraries from <code>/system/lib/asan</code> are preferred to normal libraries
203in <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
206the 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
211AddressSanitizer 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
221flashed 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
228the 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
233second build overwrite the ones from the first build. ASan-instrumented
234executables 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
240targets 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
251version 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
254code 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>