Skip to content

Commit 3c695df

Browse files
committed
[TySan][Clang] Add clang flag to use tysan outlined instrumentation and update docs
1 parent 3c4fece commit 3c695df

File tree

6 files changed

+90
-3
lines changed

6 files changed

+90
-3
lines changed

clang/docs/TypeSanitizer.rst

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,13 @@ code is build with ``-fno-strict-aliasing``, sacrificing performance.
2020
TypeSanitizer is built to catch when these strict aliasing rules have been violated, helping
2121
users find where such bugs originate in their code despite the code looking valid at first glance.
2222

23-
As TypeSanitizer is still experimental, it can currently have a large impact on runtime speed,
24-
memory use, and code size. It also has a large compile-time overhead. Work is being done to
25-
reduce these impacts.
23+
Typical memory overhead introduced by TypeSanitizer is about **8x**. Runtime slowdown varies greatly
24+
depending on how often the instrumented code relies on type aliasing. In the best case slowdown is
25+
**2x-3x**.
26+
27+
The compiler instrumentation also has an impact on code size and compilation overhead. There is an
28+
experimental :ref:`instrumentation outlining option<outlining_flag>` which can greatly reduce this
29+
but this may decrease runtime performance.
2630

2731
The TypeSanitizer Algorithm
2832
===========================
@@ -128,6 +132,23 @@ references to LLVM IR specific terms.
128132
Sanitizer features
129133
==================
130134

135+
.. _outlining_flag:
136+
137+
Instrumentation code outlining
138+
------------------------------
139+
140+
By default TypeSanitizer inlines the instrumentation code. This leads to increased
141+
binary size and compilation time. Using the clang flag
142+
``-fsanitize-type-outline-instrumentation`` (default: ``false``)
143+
forces all code instrumentation to be outlined. This reduces the size of the
144+
generated code and reduces compile-time overhead, but it also reduces runtime
145+
performance.
146+
147+
This outlined instrumentation is new. If you wish to verify that the outlined instrumentation
148+
is behaving in the same way as the inline instrumentation, you can force TypeSanitizer
149+
to use both types of instrumentation. You can use the clang flag
150+
``-fsanitize-type-verify-outlined-instrumentation`` (default: ``false``) to do this.
151+
131152
``__has_feature(type_sanitizer)``
132153
------------------------------------
133154

clang/docs/UsersManual.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2277,6 +2277,15 @@ are listed below.
22772277

22782278
See :doc: `AddressSanitizer` for more details.
22792279

2280+
.. option:: -f[no-]sanitize-type-outline-instrumentation
2281+
2282+
Controls how type sanitizer code is generated. If enabled will always use
2283+
a function call instead of inlining the code. Turning this option on may
2284+
reduce the binary size and compilation overhead, but might result in a worse
2285+
run-time performance.
2286+
2287+
See :doc: `TypeSanitizer` for more details.
2288+
22802289
.. option:: -f[no-]sanitize-stats
22812290

22822291
Enable simple statistics gathering for the enabled sanitizers.

clang/include/clang/Driver/Options.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2454,6 +2454,18 @@ def fsanitize_address_outline_instrumentation : Flag<["-"], "fsanitize-address-o
24542454
def fno_sanitize_address_outline_instrumentation : Flag<["-"], "fno-sanitize-address-outline-instrumentation">,
24552455
Group<f_clang_Group>,
24562456
HelpText<"Use default code inlining logic for the address sanitizer">;
2457+
def fsanitize_type_outline_instrumentation : Flag<["-"], "fsanitize-type-outline-instrumentation">,
2458+
Group<f_clang_Group>,
2459+
HelpText<"Always generate function calls for type sanitizer instrumentation">;
2460+
def fno_sanitize_type_outline_instrumentation : Flag<["-"], "fno-sanitize-type-outline-instrumentation">,
2461+
Group<f_clang_Group>,
2462+
HelpText<"Use default code inlining logic for the type sanitizer">;
2463+
def fsanitize_type_verify_outlined_instrumentation : Flag<["-"], "fsanitize_type_verify_outlined_instrumentation">,
2464+
Group<f_clang_Group>,
2465+
HelpText<"Use both inlined and outlined instrumentation for type sanitizer to verify equivilence">;
2466+
def fno_sanitize_type_verify_outlined_instrumentation : Flag<["-"], "fno_sanitize_type_verify_outlined_instrumentation">,
2467+
Group<f_clang_Group>,
2468+
HelpText<"Don't use both inlined and outlined instrumentation for type sanitizer to verify equivilence">;
24572469
defm sanitize_stable_abi
24582470
: OptInCC1FFlag<"sanitize-stable-abi", "Stable ", "Conventional ",
24592471
"ABI instrumentation for sanitizer runtime. Default: Conventional">;

clang/include/clang/Driver/SanitizerArgs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ class SanitizerArgs {
6767
bool TsanFuncEntryExit = true;
6868
bool TsanAtomics = true;
6969
bool MinimalRuntime = false;
70+
bool TysanOutlineInstrumentation = false;
71+
bool TysanVerifyOutlinedInstrumentation = false;
7072
// True if cross-dso CFI support if provided by the system (i.e. Android).
7173
bool ImplicitCfiRuntime = false;
7274
bool NeedsMemProfRt = false;

clang/lib/Driver/SanitizerArgs.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,6 +1176,17 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
11761176
options::OPT_fno_sanitize_alloc_token_extended, AllocTokenExtended);
11771177
}
11781178

1179+
if (AllAddedKinds & SanitizerKind::Type) {
1180+
TysanOutlineInstrumentation =
1181+
Args.hasFlag(options::OPT_fsanitize_type_outline_instrumentation,
1182+
options::OPT_fno_sanitize_type_outline_instrumentation,
1183+
TysanOutlineInstrumentation);
1184+
TysanVerifyOutlinedInstrumentation = Args.hasFlag(
1185+
options::OPT_fsanitize_type_verify_outlined_instrumentation,
1186+
options::OPT_fno_sanitize_type_verify_outlined_instrumentation,
1187+
TysanVerifyOutlinedInstrumentation);
1188+
}
1189+
11791190
LinkRuntimes = Args.hasFlag(options::OPT_fsanitize_link_runtime,
11801191
options::OPT_fno_sanitize_link_runtime,
11811192
!Args.hasArg(options::OPT_r));
@@ -1500,6 +1511,15 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
15001511
CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
15011512
}
15021513

1514+
if (TysanOutlineInstrumentation || TysanVerifyOutlinedInstrumentation) {
1515+
CmdArgs.push_back("-mllvm");
1516+
CmdArgs.push_back("-tysan-outline-instrumentation");
1517+
}
1518+
if (TysanVerifyOutlinedInstrumentation) {
1519+
CmdArgs.push_back("-mllvm");
1520+
CmdArgs.push_back("-tysan-verify-outlined-instrumentation");
1521+
}
1522+
15031523
// When emitting Stable ABI instrumentation, force outlining calls and avoid
15041524
// inlining shadow memory poisoning. While this is a big performance burden
15051525
// for now it allows full abstraction from implementation details.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %clang -S -fsanitize=type -emit-llvm -o - -fsanitize=type %s \
2+
// RUN: | FileCheck %s --check-prefixes=CHECK-NO-OUTLINE
3+
// RUN: %clang -S -fsanitize=type -emit-llvm -o - -fsanitize=type %s \
4+
// RUN: -fsanitize-type-outline-instrumentation \
5+
// RUN: | FileCheck %s --check-prefixes=CHECK-OUTLINE
6+
7+
// RUN: %clang -S -fsanitize=type -emit-llvm -o - -fsanitize=type %s \
8+
// RUN: -fsanitize-type-outline-instrumentation \
9+
// RUN: -fsanitize-type-verify-outlined-instrumentation \
10+
// RUN: | FileCheck %s --check-prefixes=CHECK-OUTLINE-VERIFY
11+
// RUN: %clang -S -fsanitize=type -emit-llvm -o - -fsanitize=type %s \
12+
// RUN: -fsanitize-type-verify-outlined-instrumentation \
13+
// RUN: | FileCheck %s --check-prefixes=CHECK-VERIFY
14+
15+
// CHECK-NO-OUTLINE-NOT: call{{.*}}@__tysan_instrument_mem_inst
16+
// CHECK-OUTLINE: call{{.*}}@__tysan_instrument_mem_inst
17+
// CHECK-OUTLINE-VERIFY: call{{.*}}@__tysan_instrument_mem_inst
18+
// CHECK-VERIFY: call{{.*}}@__tysan_instrument_mem_inst
19+
20+
float alias(int *ptr){
21+
float *aliasedPtr = (float *)ptr;
22+
return *aliasedPtr;
23+
}

0 commit comments

Comments
 (0)