1## Native Code Coverage for Android 2 3## Scope 4 5These instructions are for Android developers to collect and inspect code 6coverage for C++ and Rust code on the Android platform. 7 8## Building with Native Code Coverage Instrumentation 9 10Identify the paths where native code-coverage instrumentation should be enabled 11and set up the following environment variables. 12 13``` 14 export CLANG_COVERAGE=true 15 export NATIVE_COVERAGE_PATHS="<paths-to-instrument-for-coverage>" 16``` 17 18`NATIVE_COVERAGE_PATHS` should be a list of paths. Any Android.bp module defined 19under these paths is instrumented for code-coverage. E.g: 20 21``` 22export NATIVE_COVERAGE_PATHS="external/libcxx system/core/adb" 23``` 24 25### Additional Notes 26 27- Native Code coverage is not supported for host modules or `Android.mk` 28 modules. 29- `NATIVE_COVERAGE_PATHS="*"` enables coverage instrumentation for all paths. 30- Set `native_coverage: false` blueprint property to always disable code 31 coverage instrumentation for a module. This is useful if this module has 32 issues when building or running with coverage. 33- `NATIVE_COVERAGE_EXCLUDE_PATHS` can be set to exclude subdirs under 34 `NATIVE_COVERAGE_PATHS` from coverage instrumentation. E.g. 35 `NATIVE_COVERAGE_PATHS=frameworks/native 36 NATIVE_COVERAGE_PATHS=frameworks/native/vulkan` will instrument all native 37 code under `frameworks/native` except`frameworks/native/vulkan`. 38 39## Running Tests 40 41### Collecting Profiles 42 43When an instrumented program is run, the profiles are stored to the path and 44name specified in the `LLVM_PROFILE_FILE` environment variable. On Android 45coverage builds it is set to `/data/misc/trace/clang-%p-%20m.profraw`. 46 47* `%`p is replaced by the pid of the process 48* `%m` by the hash of the library/binary 49* The `20` in`%20m` creates a pool of 20 profraw files and "online" profile 50 merging is used to merge coverage to profiles onto this pool. 51 52Reference:`LLVM_PROFILE_FILE` can include additional specifiers as described 53[here](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#running-the-instrumented-program). 54 55For this and following steps, use the `acov-llvm.py` script: 56`$ANDROID_BUILD_TOP/development/scripts/acov-llvm.py`. 57 58There may be profiles in `/data/misc/trace` collected before the test is run. 59Clear this data before running the test. 60 61``` 62 # Clear any coverage that's already written to /data/misc/trace 63 # and reset coverage for all daemons. 64 <host>$ acov-llvm.py clean-device 65 66 # Run the test. The exact command depends on the nature of the test. 67 <device>$ /data/local/tmp/$MY_TEST 68``` 69 70For tests that exercise a daemon/service running in another process, write out 71the coverage for those processes as well. 72 73``` 74 # Flush coverage of all daemons/processes running on the device. 75 <host>$ acov-llvm.py flush 76 77 # Flush coverage for a particular daemon, say adbd. 78 <host>$ acov-llvm.py flush adbd 79``` 80 81## Viewing Coverage Data (acov-llvm.py) 82 83To post-process and view coverage information we use the `acov-llvm.py report` 84command. It invokes two LLVM utilities `llvm-profdata` and `llvm-cov`. An 85advanced user can manually invoke these utilities for fine-grained control. This 86is discussed [below](#viewing-coverage-data-manual). 87 88To generate coverage report need the following parameters. These are dependent 89on the test/module: 90 911. One or more binaries and shared libraries from which coverage was collected. 92 E.g.: 93 94 1. ART mainline module contains a few libraries such as `libart.so`, 95 `libart-compiler.so`. 96 2. Bionic tests exercise code in `libc.so` and `libm.so`. 97 98 We need the *unstripped* copies of these binaries. Source information 99 included in the debuginfo is used to process the coverage data. 100 1012. One or more source directories under `$ANDROID_BUILD_TOP` for which coverage 102 needs to be reported. 103 104Invoke the report subcommand of acov-llvm.py to produce a html coverage summary: 105 106``` 107 $ acov-llvm.py report \ 108 -s <one-or-more-source-paths-in-$ANDROID_BUILD_TOP \ 109 -b <one-or-more-(unstripped)-binaries-in-$OUT> 110``` 111 112E.g.: 113 114``` 115 $ acov-llvm.py report \ 116 -s bionic \ 117 -b \ 118 $OUT/symbols/apex/com.android.runtime/lib/bionic/libc.so \ 119 $OUT/symbols/apex/com.android.runtime/lib/bionic/libm.so 120``` 121 122The script will produce a report in a temporary directory under 123`$ANDROID_BUILD_TOP`. It'll produce a log as below: 124 125``` 126 generating coverage report in covreport-xxxxxx 127``` 128 129A html report would be generated under `covreport-xxxxxx/html`. 130 131## Viewing Coverage Data (manual) 132 133`acov-llvm.py report` does a few operations under the hood which we can also 134manually invoke for flexibility. 135 136### Post-processing Coverage Files 137 138Fetch coverage files from the device and post-process them to a `.profdata` file 139as follows: 140 141``` 142 # Fetch the coverage data from the device. 143 <host>$ cd coverage_data 144 <host>$ adb pull /data/misc/trace/ $TRACE_DIR_HOST 145 146 # Convert from .profraw format to the .profdata format. 147 <host>$ llvm-profdata merge --output=$MY_TEST.profdata \ 148 $TRACE_DIR_HOST/clang-*.profraw 149``` 150 151For added specificity, restrict the above command to just the <PID>s of the 152daemon or test processes of interest. 153 154``` 155 <host>$ llvm-profdata merge --output=$MY_TEST.profdata \ 156 $MY_TEST.profraw \ 157 trace/clang-<pid1>.profraw trace/clang-<pid2>.profraw ... 158``` 159 160### Generating Coverage report 161 162Documentation on Clang source-instrumentation-based coverage is available 163[here](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#creating-coverage-reports). 164The `llvm-cov` utility is used to show coverage from a `.profdata` file. The 165documentation for commonly used `llvm-cov` command-line arguments is available 166[here](https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-report). (Try 167`llvm-cov show --help` for a complete list). 168 169#### `show` subcommand 170 171The `show` command displays the function and line coverage for each source file 172in the binary. 173 174``` 175 <host>$ llvm-cov show \ 176 --show-region-summary=false 177 --format=html --output-dir=coverage-html \ 178 --instr-profile=$MY_TEST.profdata \ 179 $MY_BIN \ 180``` 181 182* In the above command, `$MY_BIN` should be the unstripped binary (i.e. with 183 debuginfo) since `llvm-cov` reads some debuginfo to process the coverage 184 data. 185 186 E.g.: 187 188 ~~~ 189 ``` 190 <host>$ llvm-cov report \ 191 --instr-profile=adbd.profdata \ 192 $LOCATION_OF_UNSTRIPPED_ADBD/adbd \ 193 --show-region-summary=false 194 ``` 195 ~~~ 196 197* The `-ignore-filename-regex=<regex>` option can be used to ignore files that 198 are not of interest. E.g: `-ignore-filename-regex="external/*"` 199 200* Use the `--object=<BIN>` argument to specify additional binaries and shared 201 libraries whose coverage is included in this profdata. See the earlier 202 [section](#viewing-coverage-data-acov-llvm-py) for examples where more than 203 one binary may need to be used. 204 205 E.g., the following command is used for `bionic-unit-tests`, which tests 206 both `libc.so` and `libm.so`: 207 208 ~~~ 209 ``` 210 <host>$ llvm-cov report \ 211 --instr-profile=bionic.profdata \ 212 $OUT/.../libc.so \ 213 --object=$OUT/.../libm.so 214 ``` 215 ~~~ 216 217* `llvm-cov` also takes positional SOURCES argument to consider/display only 218 particular paths of interest. E.g: 219 220 ~~~ 221 ``` 222 <host>$ llvm-cov report \ 223 --instr-profile=adbd.profdata \ 224 $LOCATION_OF_ADBD/adbd \ 225 --show-region-summary=false \ 226 /proc/self/cwd/system/core/adb 227 ``` 228 ~~~ 229 230Note that the paths for the sources need to be prepended with 231'`/proc/self/cwd/`'. This is because Android C/C++ compilations run with 232`PWD=/proc/self/cwd` and consequently the source names are recorded with that 233prefix. Alternatively, the 234[`--path-equivalence`](https://llvm.org/docs/CommandGuide/llvm-cov.html#cmdoption-llvm-cov-show-path-equivalence) 235option to `llvm-cov` can be used. 236 237#### `report` subcommand 238 239The [`report`](https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-report) 240subcommand summarizes the percentage of covered lines to the console. It takes 241options similar to the `show` subcommand. 242