Docs: Improve asan.md formatting
Improves the asan.md doc formatting, mostly as per review comments in https://crrev.com/c/1883615/. Change-Id: Ib4e51353b306d71f231521bd2f07944f13207c98 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1972418 Commit-Queue: Darwin Huang <huangdarwin@chromium.org> Auto-Submit: Darwin Huang <huangdarwin@chromium.org> Reviewed-by: Victor Costan <pwnall@chromium.org> Cr-Commit-Position: refs/heads/master@{#727205}
This commit is contained in:
128
docs/asan.md
128
docs/asan.md
@ -4,7 +4,7 @@
|
||||
error detector based on compiler instrumentation (LLVM). It is fully usable for
|
||||
Chrome on Linux and Mac. There's a mostly-functional Windows port in progress
|
||||
too. Additional info on the tool itself is available at
|
||||
http://clang.llvm.org/docs/AddressSanitizer.html.
|
||||
https://clang.llvm.org/docs/AddressSanitizer.html.
|
||||
|
||||
For the memory leak detector built into ASan, see
|
||||
[LeakSanitizer](https://sites.google.com/a/chromium.org/dev/developers/testing/leaksanitizer).
|
||||
@ -22,14 +22,12 @@ and 64 bits), Chromium OS (x86 and amd64 builds running inside VMs). Linux and
|
||||
Linux Chromium OS bots run with --no-sandbox, but there's an extra Linux bot
|
||||
that enables the sandbox (but disables LeakSanitizer).
|
||||
|
||||
The trybots running Chromium tests on Linux and OSX are: linux_asan (everything
|
||||
except browser_tests and content_browsertests), linux_browser_asan
|
||||
(browser_tests and content_browsertests), mac_asan (many tests including
|
||||
browser_tests and content_browsertests), linux_chromeos_asan (the chromeos=1
|
||||
build running on a Linux machine, many tests including browser_tests and
|
||||
content_browsertests).
|
||||
|
||||
(Outdated) Blink bots: WebKit Linux ASAN buildbot and linux_layout_asan trybot.
|
||||
The trybots running Chromium tests on Linux and macOS are:
|
||||
- linux_asan (everything except browser_tests and content_browsertests)
|
||||
- linux_browser_asan (browser_tests and content_browsertests),
|
||||
- mac_asan (many tests including browser_tests and content_browsertests)
|
||||
- linux_chromeos_asan (the chromeos=1 build running on a Linux machine, many
|
||||
tests including browser_tests and content_browsertests).
|
||||
|
||||
## Pre-built Chrome binaries
|
||||
|
||||
@ -38,8 +36,8 @@ You can grab fresh Chrome binaries built with ASan
|
||||
|
||||
## Build tests with ASan
|
||||
|
||||
If you're on mac or linux64, building with ASan is easy. Start by compiling
|
||||
`base_unittests` to verify the build is working for you (see below), then you
|
||||
If you're on MacOS or linux64, building with ASan is easy. Start by compiling
|
||||
`base_unittests` to verify the build is working for you (see below). Then, you
|
||||
can compile `chrome`, `browser_tests`, etc.. Make sure to compile release
|
||||
builds.
|
||||
|
||||
@ -50,18 +48,18 @@ details).
|
||||
### Configuring the build
|
||||
|
||||
Create an asan build directory by running:
|
||||
```
|
||||
```shell
|
||||
gn args out/asan
|
||||
```
|
||||
|
||||
Enter the following build variables in the editor that will pop up:
|
||||
```
|
||||
```python
|
||||
is_asan = true
|
||||
is_debug = false # Release build.
|
||||
```
|
||||
|
||||
Build with:
|
||||
```
|
||||
```shell
|
||||
ninja -C out/asan base_unittests
|
||||
```
|
||||
|
||||
@ -75,7 +73,7 @@ forget to use ninja -j <jobs> to take advantage of goma.
|
||||
|
||||
If you want your stack traces to be precise, you will have to disable inlining
|
||||
by setting the GN arg:
|
||||
```
|
||||
```shell
|
||||
enable_full_stack_frames_for_profiling = true
|
||||
```
|
||||
|
||||
@ -83,11 +81,10 @@ Note that this incurs a significant performance hit. Please do not do this on
|
||||
buildbots.
|
||||
|
||||
If you're working on reproducing ClusterFuzz reports, you might want to add:
|
||||
```
|
||||
```shell
|
||||
v8_enable_verify_heap = true
|
||||
```
|
||||
|
||||
in order to enable the --verify-heap command line flag for v8 in Release builds.
|
||||
in order to enable the `--verify-heap` command line flag for v8 in Release builds.
|
||||
|
||||
## Verify the ASan tool works
|
||||
|
||||
@ -99,21 +96,23 @@ the
|
||||
page instead.
|
||||
|
||||
Now, check that the tool works. Run the following:
|
||||
```
|
||||
out/asan/base_unittests
|
||||
--gtest_filter=ToolsSanityTest.DISABLED_AddressSanitizerLocalOOBCrashTest
|
||||
--gtest_also_run_disabled_tests 2>&1 | tools/valgrind/asan/asan_symbolize.py
|
||||
```shell
|
||||
out/asan/base_unittests \
|
||||
--gtest_filter=ToolsSanityTest.DISABLED_AddressSanitizerLocalOOBCrashTest \
|
||||
--gtest_also_run_disabled_tests 2>&1 | tools/valgrind/asan/asan_symbolize.py
|
||||
```
|
||||
|
||||
The test will crash with the following error report:
|
||||
```
|
||||
==26552== ERROR: AddressSanitizer stack-buffer-overflow on address 0x7fff338adb14 at pc 0xac20a7 bp 0x7fff338adad0 sp 0x7fff338adac8
|
||||
```shell
|
||||
==26552== ERROR: AddressSanitizer stack-buffer-overflow on address \
|
||||
0x7fff338adb14 at pc 0xac20a7 bp 0x7fff338adad0 sp 0x7fff338adac8
|
||||
WRITE of size 4 at 0x7fff338adb14 thread T0
|
||||
#0 0xac20a7 in base::ToolsSanityTest_DISABLED_AddressSanitizerLocalOOBCrashTest_Test::TestBody() ???:0
|
||||
#1 0xcddbd6 in testing::Test::Run() testing/gtest/src/gtest.cc:2161
|
||||
#2 0xcdf63b in testing::TestInfo::Run() testing/gtest/src/gtest.cc:2338
|
||||
... lots more stuff
|
||||
Address 0x7fff338adb14 is located at offset 52 in frame <base::ToolsSanityTest_DISABLED_AddressSanitizerLocalOOBCrashTest_Test::TestBody()> of T0's stack:
|
||||
Address 0x7fff338adb14 is located at offset 52 in frame \
|
||||
base::ToolsSanityTest_DISABLED_AddressSanitizerLocalOOBCrashTest_Test::TestBody()> of T0's stack:
|
||||
This frame has 2 object(s):
|
||||
[32, 52) 'array'
|
||||
[96, 104) 'access'
|
||||
@ -125,7 +124,7 @@ Congrats, you have a working ASan build! 🙌
|
||||
|
||||
## Run chrome under ASan
|
||||
|
||||
And finally, have fun with the `out/Release/chrome binary`. The filter script
|
||||
And finally, have fun with the `out/Release/chrome` binary. The filter script
|
||||
`tools/valgrind/asan/asan_symbolize.py` should be used to symbolize the output.
|
||||
(Note that `asan_symbolize.py` is absolutely necessary if you need the symbols -
|
||||
there is no built-in symbolizer for ASan in Chrome).
|
||||
@ -156,7 +155,7 @@ See `base/debug/sanitizer_options.cc` for more details.
|
||||
|
||||
## NaCl support under ASan
|
||||
|
||||
On Linux (and soon on Mac) you can build and run Chromium with NaCl under ASan.
|
||||
On Linux (and soon on MacOS) you can build and run Chromium with NaCl under ASan.
|
||||
Untrusted code (nexe) itself is not instrumented with ASan in this mode, but
|
||||
everything else is.
|
||||
|
||||
@ -165,7 +164,8 @@ To do this, remove `disable_nacl=1` from `GYP_DEFINES`, and define
|
||||
|
||||
Pipe chromium output (stderr) through ``tools/valgrind/asan/asan_symbolize.py
|
||||
`pwd`/`` to get function names and line numbers in ASan reports.
|
||||
If you're seeing crashes within `nacl_helper_bootstrap`, try deleting `out/Release/nacl_helper`.
|
||||
If you're seeing crashes within `nacl_helper_bootstrap`, try deleting
|
||||
`out/Release/nacl_helper`.
|
||||
|
||||
## Building on iOS
|
||||
|
||||
@ -175,10 +175,12 @@ for that. It isn't currently possible to build iOS binaries targeting ARM.
|
||||
|
||||
Configure your build with `is_asan = true` as described above. Replace your
|
||||
build directory as needed:
|
||||
```
|
||||
```shell
|
||||
ninja -C out/Release-iphonesimulator base_unittests
|
||||
out/Release-iphonesimulator/iossim -d "iPhone" -s 7.0 out/Release-iphonesimulator/base_unittests.app/ \
|
||||
--gtest_filter=ToolsSanityTest.DISABLED_AddressSanitizerLocalOOBCrashTest --gtest_also_run_disabled_tests 2>&1 |
|
||||
out/Release-iphonesimulator/iossim -d "iPhone" -s 7.0 \
|
||||
out/Release-iphonesimulator/base_unittests.app/ \
|
||||
--gtest_filter=ToolsSanityTest.DISABLED_AddressSanitizerLocalOOBCrashTest \
|
||||
--gtest_also_run_disabled_tests 2>&1 |
|
||||
tools/valgrind/asan/asan_symbolize.py
|
||||
```
|
||||
|
||||
@ -190,22 +192,24 @@ section), with a number of iOS-specific frames.
|
||||
Follow [AndroidBuildInstructions](android_build_instructions.md) with minor
|
||||
changes:
|
||||
|
||||
target_os="android"
|
||||
is_clang=true
|
||||
is_asan=true
|
||||
is_debug=false
|
||||
```python
|
||||
target_os="android"
|
||||
is_clang=true
|
||||
is_asan=true
|
||||
is_debug=false
|
||||
```
|
||||
|
||||
Running ASan applications on Android requires additional device setup. Chromium
|
||||
testing scripts take care of this, so testing works as expected:
|
||||
```
|
||||
build/android/test_runner.py instrumentation --test-apk ContentShellTest
|
||||
--test_data content:content/test/data/android/device_files -v -v -v --tool=asan
|
||||
--release
|
||||
```shell
|
||||
build/android/test_runner.py instrumentation --test-apk ContentShellTest \
|
||||
--test_data content:content/test/data/android/device_files -v -v -v \
|
||||
--tool=asan --release
|
||||
```
|
||||
|
||||
To run stuff without Chromium testing script (ex. ContentShell.apk, or any third
|
||||
party apk or binary), device setup is needed:
|
||||
```
|
||||
```shell
|
||||
tools/android/asan/third_party/asan_device_setup.sh --lib
|
||||
third_party/llvm-build/Release+Asserts/lib/clang/*/lib/linux/libclang_rt.asan-arm-android.so
|
||||
# wait a few seconds for the device to reload
|
||||
@ -216,11 +220,13 @@ When this is done, the device will run ASan apks as well as normal apks without
|
||||
any further setup.
|
||||
|
||||
To run command-line tools (i.e. binaries), prefix them with `asanwrapper`:
|
||||
```
|
||||
```shell
|
||||
adb shell /system/bin/asanwrapper /path/to/binary
|
||||
```
|
||||
|
||||
Use `build/android/asan_symbolize.py` to symbolize stack from `adb logcat`. It needs the `--output-directory` argument and takes care of translating the device path to the unstripped binary in the output directory.
|
||||
Use `build/android/asan_symbolize.py` to symbolize stack from `adb logcat`. It
|
||||
needs the `--output-directory` argument and takes care of translating the device
|
||||
path to the unstripped binary in the output directory.
|
||||
|
||||
## Building with v8_target_arch=arm
|
||||
|
||||
@ -228,26 +234,30 @@ This is needed to detect addressability bugs in the ARM code emitted by V8 and
|
||||
running on an instrumented ARM emulator in a 32-bit x86 Linux Chromium. **You
|
||||
probably don't want this, and these instructions have bitrotted because they
|
||||
still reference GYP. If you do this successfully, please update!** See
|
||||
[http://crbug.com/324207](https://bugs.chromium.org/p/chromium/issues/detail?id=324207)
|
||||
for some context.
|
||||
https://crbug.com/324207 for some context.
|
||||
|
||||
First, you need to install the 32-bit chroot environment using the
|
||||
`build/install-chroot.sh` script (as described in
|
||||
https://code.google.com/p/chromium/wiki/LinuxBuild32On64). Second, install the
|
||||
build deps:
|
||||
```
|
||||
precise32 build/install-build-deps.sh # assuming your schroot wrapper is called 'precise32'
|
||||
```shell
|
||||
precise32 build/install-build-deps.sh \
|
||||
# assuming your schroot wrapper is called 'precise32'
|
||||
```
|
||||
|
||||
You'll need to make two symlinks to avoid linking errors:
|
||||
```
|
||||
sudo ln -s $CHROOT/usr/lib/i386-linux-gnu/libc_nonshared.a /usr/lib/i386-linux-gnu/libc_nonshared.a
|
||||
sudo ln -s $CHROOT/usr/lib/i386-linux-gnu/libpthread_nonshared.a /usr/lib/i386-linux-gnu/libpthread_nonshared.a
|
||||
```shell
|
||||
sudo ln -s $CHROOT/usr/lib/i386-linux-gnu/libc_nonshared.a \
|
||||
/usr/lib/i386-linux-gnu/libc_nonshared.a
|
||||
sudo ln -s $CHROOT/usr/lib/i386-linux-gnu/libpthread_nonshared.a \
|
||||
/usr/lib/i386-linux-gnu/libpthread_nonshared.a
|
||||
```
|
||||
|
||||
Now configure and build your Chrome:
|
||||
```
|
||||
GYP_GENERATOR_FLAGS="output_dir=out_asan_chroot" GYP_DEFINES="asan=1 disable_nacl=1 v8_target_arch=arm sysroot=/var/lib/chroot/precise32bit/ chroot_cmd=precise32 host_arch=x86_64 target_arch=ia32" gclient runhooks
|
||||
```shell
|
||||
GYP_GENERATOR_FLAGS="output_dir=out_asan_chroot" GYP_DEFINES="asan=1 \
|
||||
disable_nacl=1 v8_target_arch=arm sysroot=/var/lib/chroot/precise32bit/ \
|
||||
chroot_cmd=precise32 host_arch=x86_64 target_arch=ia32" gclient runhooks
|
||||
ninja -C out_asan_chroot/Release chrome
|
||||
```
|
||||
|
||||
@ -264,9 +274,9 @@ args. See also the `sanitizer_coverage_flags` variable for configuring it.
|
||||
Chrome must be terminated gracefully in order for coverage to work. Either close
|
||||
the browser, or SIGTERM the browser process. Do not do `killall chrome` or send
|
||||
SIGKILL.
|
||||
```
|
||||
$ kill <browser_process_pid>
|
||||
$ ls
|
||||
```shell
|
||||
kill <browser_process_pid>
|
||||
ls
|
||||
...
|
||||
chrome.22575.sancov
|
||||
gpu.6916123572022919124.sancov.packed
|
||||
@ -278,8 +288,9 @@ The `gpu.*.sancov.packed` file contains coverage data for the GPU process,
|
||||
whereas the `zygote.*.sancov.packed` file contains coverage data for the
|
||||
renderers (but not the zygote process). Unpack them to regular `.sancov` files
|
||||
like so:
|
||||
```
|
||||
$ $LLVM/projects/compiler-rt/lib/sanitizer_common/scripts/sancov.py unpack *.sancov.packed
|
||||
```shell
|
||||
$ $LLVM/projects/compiler-rt/lib/sanitizer_common/scripts/sancov.py unpack \
|
||||
*.sancov.packed
|
||||
sancov.py: unpacking gpu.6916123572022919124.sancov.packed
|
||||
sancov.py: extracting chrome.22610.sancov
|
||||
sancov.py: unpacking zygote.13651804083035800069.sancov.packed
|
||||
@ -291,6 +302,7 @@ sancov.py: extracting chrome.10.sancov
|
||||
|
||||
Now, e.g., to list the offsets of covered functions in the libpdf.so binary in
|
||||
renderer with pid 10:
|
||||
```
|
||||
$ $LLVM/projects/compiler-rt/lib/sanitizer_common/scripts/sancov.py print libpdf.so.10.sancov
|
||||
```shell
|
||||
$ $LLVM/projects/compiler-rt/lib/sanitizer_common/scripts/sancov.py print \
|
||||
libpdf.so.10.sancov
|
||||
```
|
||||
|
Reference in New Issue
Block a user