and runtime libraries. Highlight of the most important aspects of the
implementation:
* The sanitizer runtime libraries are part of the [compiler-rt] project, and
[will be built][sanitizer-build] on [supported targets][sanitizer-targets]
when enabled in `bootstrap.toml`:
```toml
[build]
sanitizers = true
```
The runtimes are [placed into target libdir][sanitizer-copy].
* During LLVM code generation, the functions intended for instrumentation are
[marked][sanitizer-attribute] with appropriate LLVM attribute:
`SanitizeAddress`, `SanitizeHWAddress`, `SanitizeMemory`, or
`SanitizeThread`. By default all functions are instrumented, but this
behaviour can be changed with `#[no_sanitize(...)]`.
* The decision whether to perform instrumentation or not is possible only at a
function granularity. In the cases were those decision differ between
functions it might be necessary to inhibit inlining, both at [MIR
level][inline-mir] and [LLVM level][inline-llvm].
* The LLVM IR generated by rustc is instrumented by [dedicated LLVM
passes][sanitizer-pass], different for each sanitizer. Instrumentation
passes are invoked after optimization passes.
* When producing an executable, the sanitizer specific runtime library is
[linked in][sanitizer-link]. The libraries are searched for in the target
libdir. First relative to the overridden system root and subsequently
relative to the default system root. Fall-back to the default system root
ensures that sanitizer runtimes remain available when using sysroot overrides
constructed by cargo `-Z build-std` or xargo.
## Testing sanitizers
Sanitizers are validated by code generation tests in
[`tests/codegen/sanitize*.rs`][test-cg] and end-to-end functional tests in
[`tests/ui/sanitizer/`][test-ui] directory.
Testing sanitizer functionality requires the sanitizer runtimes (built when
`sanitizer = true` in `bootstrap.toml`) and target providing support for particular
sanitizer. When sanitizer is unsupported on given target, sanitizers tests will
be ignored. This behaviour is controlled by compiletest `needs-sanitizer-*`
directives.
## Enabling sanitizer on a new target
To enable a sanitizer on a new target which is already supported by LLVM:
1. Include the sanitizer in the list of `supported_sanitizers` in [the target
definition][target-definition]. `rustc --target .. -Zsanitizer=..` should now
recognize sanitizer as supported.
2. [Build the runtime for the target and include it in the libdir.][sanitizer-targets]
3. [Teach compiletest that your target now supports the sanitizer.][compiletest-definition]
Tests marked with `needs-sanitizer-*` should now run on the target.
4. Run tests `./x test --force-rerun tests/ui/sanitize/` to verify.
5. [--enable-sanitizers in the CI configuration][ci-configuration] to build and
distribute the sanitizer runtime as part of the release process.
## Additional Information
* [Sanitizers project page](https://github.com/google/sanitizers/wiki/)
* [AddressSanitizer in Clang][clang-asan]
* [ControlFlowIntegrity in Clang][clang-cfi]
* [Hardware-assisted AddressSanitizer][clang-hwasan]
* [KernelControlFlowIntegrity in Clang][clang-kcfi]
* [LeakSanitizer in Clang][clang-lsan]
* [MemorySanitizer in Clang][clang-msan]
* [ThreadSanitizer in Clang][clang-tsan]