[SCCP] Avoid modifying AdditionalUsers while iterating over it
[llvm-project.git] / clang / docs / DataFlowSanitizer.rst
blob6b5c1e14e134f0b1736186c2bc1647b1b1bf53a5
1 =================
2 DataFlowSanitizer
3 =================
5 .. toctree::
6    :hidden:
8    DataFlowSanitizerDesign
10 .. contents::
11    :local:
13 Introduction
14 ============
16 DataFlowSanitizer is a generalised dynamic data flow analysis.
18 Unlike other Sanitizer tools, this tool is not designed to detect a
19 specific class of bugs on its own.  Instead, it provides a generic
20 dynamic data flow analysis framework to be used by clients to help
21 detect application-specific issues within their own code.
23 How to build libc++ with DFSan
24 ==============================
26 DFSan requires either all of your code to be instrumented or for uninstrumented
27 functions to be listed as ``uninstrumented`` in the `ABI list`_.
29 If you'd like to have instrumented libc++ functions, then you need to build it
30 with DFSan instrumentation from source. Here is an example of how to build
31 libc++ and the libc++ ABI with data flow sanitizer instrumentation.
33 .. code-block:: console
35   cd libcxx-build
37   # An example using ninja
38   cmake -GNinja path/to/llvm-project/llvm \
39     -DCMAKE_C_COMPILER=clang \
40     -DCMAKE_CXX_COMPILER=clang++ \
41     -DLLVM_USE_SANITIZER="DataFlow" \
42     -DLLVM_ENABLE_LIBCXX=ON \
43     -DLLVM_ENABLE_PROJECTS="libcxx;libcxxabi"
45   ninja cxx cxxabi
47 Note: Ensure you are building with a sufficiently new version of Clang.
49 Usage
50 =====
52 With no program changes, applying DataFlowSanitizer to a program
53 will not alter its behavior.  To use DataFlowSanitizer, the program
54 uses API functions to apply tags to data to cause it to be tracked, and to
55 check the tag of a specific data item.  DataFlowSanitizer manages
56 the propagation of tags through the program according to its data flow.
58 The APIs are defined in the header file ``sanitizer/dfsan_interface.h``.
59 For further information about each function, please refer to the header
60 file.
62 .. _ABI list:
64 ABI List
65 --------
67 DataFlowSanitizer uses a list of functions known as an ABI list to decide
68 whether a call to a specific function should use the operating system's native
69 ABI or whether it should use a variant of this ABI that also propagates labels
70 through function parameters and return values.  The ABI list file also controls
71 how labels are propagated in the former case.  DataFlowSanitizer comes with a
72 default ABI list which is intended to eventually cover the glibc library on
73 Linux but it may become necessary for users to extend the ABI list in cases
74 where a particular library or function cannot be instrumented (e.g. because
75 it is implemented in assembly or another language which DataFlowSanitizer does
76 not support) or a function is called from a library or function which cannot
77 be instrumented.
79 DataFlowSanitizer's ABI list file is a :doc:`SanitizerSpecialCaseList`.
80 The pass treats every function in the ``uninstrumented`` category in the
81 ABI list file as conforming to the native ABI.  Unless the ABI list contains
82 additional categories for those functions, a call to one of those functions
83 will produce a warning message, as the labelling behavior of the function
84 is unknown.  The other supported categories are ``discard``, ``functional``
85 and ``custom``.
87 * ``discard`` -- To the extent that this function writes to (user-accessible)
88   memory, it also updates labels in shadow memory (this condition is trivially
89   satisfied for functions which do not write to user-accessible memory).  Its
90   return value is unlabelled.
91 * ``functional`` -- Like ``discard``, except that the label of its return value
92   is the union of the label of its arguments.
93 * ``custom`` -- Instead of calling the function, a custom wrapper ``__dfsw_F``
94   is called, where ``F`` is the name of the function.  This function may wrap
95   the original function or provide its own implementation.  This category is
96   generally used for uninstrumentable functions which write to user-accessible
97   memory or which have more complex label propagation behavior.  The signature
98   of ``__dfsw_F`` is based on that of ``F`` with each argument having a
99   label of type ``dfsan_label`` appended to the argument list.  If ``F``
100   is of non-void return type a final argument of type ``dfsan_label *``
101   is appended to which the custom function can store the label for the
102   return value.  For example:
104 .. code-block:: c++
106   void f(int x);
107   void __dfsw_f(int x, dfsan_label x_label);
109   void *memcpy(void *dest, const void *src, size_t n);
110   void *__dfsw_memcpy(void *dest, const void *src, size_t n,
111                       dfsan_label dest_label, dfsan_label src_label,
112                       dfsan_label n_label, dfsan_label *ret_label);
114 If a function defined in the translation unit being compiled belongs to the
115 ``uninstrumented`` category, it will be compiled so as to conform to the
116 native ABI.  Its arguments will be assumed to be unlabelled, but it will
117 propagate labels in shadow memory.
119 For example:
121 .. code-block:: none
123   # main is called by the C runtime using the native ABI.
124   fun:main=uninstrumented
125   fun:main=discard
127   # malloc only writes to its internal data structures, not user-accessible memory.
128   fun:malloc=uninstrumented
129   fun:malloc=discard
131   # tolower is a pure function.
132   fun:tolower=uninstrumented
133   fun:tolower=functional
135   # memcpy needs to copy the shadow from the source to the destination region.
136   # This is done in a custom function.
137   fun:memcpy=uninstrumented
138   fun:memcpy=custom
140 Example
141 =======
143 The following program demonstrates label propagation by checking that
144 the correct labels are propagated.
146 .. code-block:: c++
148   #include <sanitizer/dfsan_interface.h>
149   #include <assert.h>
151   int main(void) {
152     int i = 1;
153     dfsan_label i_label = dfsan_create_label("i", 0);
154     dfsan_set_label(i_label, &i, sizeof(i));
156     int j = 2;
157     dfsan_label j_label = dfsan_create_label("j", 0);
158     dfsan_set_label(j_label, &j, sizeof(j));
160     int k = 3;
161     dfsan_label k_label = dfsan_create_label("k", 0);
162     dfsan_set_label(k_label, &k, sizeof(k));
164     dfsan_label ij_label = dfsan_get_label(i + j);
165     assert(dfsan_has_label(ij_label, i_label));
166     assert(dfsan_has_label(ij_label, j_label));
167     assert(!dfsan_has_label(ij_label, k_label));
169     dfsan_label ijk_label = dfsan_get_label(i + j + k);
170     assert(dfsan_has_label(ijk_label, i_label));
171     assert(dfsan_has_label(ijk_label, j_label));
172     assert(dfsan_has_label(ijk_label, k_label));
174     return 0;
175   }
177 fast16labels mode
178 =================
180 If you need 16 or fewer labels, you can use fast16labels instrumentation for
181 less CPU and code size overhead.  To use fast16labels instrumentation, you'll
182 need to specify `-fsanitize=dataflow -mllvm -dfsan-fast-16-labels` in your
183 compile and link commands and use a modified API for creating and managing
184 labels.
186 In fast16labels mode, base labels are simply 16-bit unsigned integers that are
187 powers of 2 (i.e. 1, 2, 4, 8, ..., 32768), and union labels are created by ORing
188 base labels.  In this mode DFSan does not manage any label metadata, so the
189 functions `dfsan_create_label`, `dfsan_union`, `dfsan_get_label_info`,
190 `dfsan_has_label`, `dfsan_has_label_with_desc`, `dfsan_get_label_count`, and
191 `dfsan_dump_labels` are unsupported.  Instead of using them, the user should
192 maintain any necessary metadata about base labels themselves.
194 For example:
196 .. code-block:: c++
198   #include <sanitizer/dfsan_interface.h>
199   #include <assert.h>
201   int main(void) {
202     int i = 100;
203     int j = 200;
204     int k = 300;
205     dfsan_label i_label = 1;
206     dfsan_label j_label = 2;
207     dfsan_label k_label = 4;
208     dfsan_set_label(i_label, &i, sizeof(i));
209     dfsan_set_label(j_label, &j, sizeof(j));
210     dfsan_set_label(k_label, &k, sizeof(k));
212     dfsan_label ij_label = dfsan_get_label(i + j);
214     assert(ij_label & i_label);  // ij_label has i_label
215     assert(ij_label & j_label);  // ij_label has j_label
216     assert(!(ij_label & k_label));  // ij_label doesn't have k_label
217     assert(ij_label == 3);  // Verifies all of the above
219     dfsan_label ijk_label = dfsan_get_label(i + j + k);
221     assert(ijk_label & i_label);  // ijk_label has i_label
222     assert(ijk_label & j_label);  // ijk_label has j_label
223     assert(ijk_label & k_label);  // ijk_label has k_label
224     assert(ijk_label == 7);  // Verifies all of the above
226     return 0;
227   }
229 Current status
230 ==============
232 DataFlowSanitizer is a work in progress, currently under development for
233 x86\_64 Linux.
235 Design
236 ======
238 Please refer to the :doc:`design document<DataFlowSanitizerDesign>`.