From 1591d40ef935cda3109d147e88d61585cf4192bd Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Thu, 29 Sep 2016 18:58:17 +0000 Subject: [PATCH] [sanitizer-coverage] more docs git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@282751 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/SanitizerCoverage.rst | 67 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/docs/SanitizerCoverage.rst b/docs/SanitizerCoverage.rst index e2bd7fbe1d..051a365e34 100644 --- a/docs/SanitizerCoverage.rst +++ b/docs/SanitizerCoverage.rst @@ -349,6 +349,73 @@ Similarly to `trace-pc,indirect-calls`, with `trace-pc-guards,indirect-calls` The functions `__sanitizer_cov_trace_pc_*` should be defined by the user. +Example: + +.. code-block:: c++ + + // trace-pc-guard-cb.cc + #include + #include + #include + + // This callback is inserted by the compiler as a module constructor + // into every compilation unit. 'start' and 'stop' correspond to the + // beginning and end of the section with the guards for the entire + // binary (executable or DSO) and so it will be called multiple times + // with the same parameters. + extern "C" void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, + uint32_t *stop) { + static uint64_t N; // Counter for the guards. + if (start == stop || *start) return; // Initialize only once. + printf("INIT: %p %p\n", start, stop); + for (uint32_t *x = start; x < stop; x++) + *x = ++N; // Guards should start from 1. + } + + // This callback is inserted by the compiler on every edge in the + // control flow (some optimizations apply). + // Typically, the compiler will emit the code like this: + // if(*guard) + // __sanitizer_cov_trace_pc_guard(guard); + // But for large functions it will emit a simple call: + // __sanitizer_cov_trace_pc_guard(guard); + extern "C" void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { + if (!*guard) return; // Duplicate the guard check. + // If you set *guard to 0 this code will not be called again for this edge. + // Now you can get the PC and do whatever you want: + // store it somewhere or symbolize it and print right away. + // The values of `*guard` are as you set them in + // __sanitizer_cov_trace_pc_guard_init and so you can make the consecutive + // and use them to dereference an array or a bit vector. + void *PC = __builtin_return_address(0); + char PcDescr[1024]; + // This function is a part of the sanitizer run-time. + // To use it, link with AddressSanitizer or other sanitizer. + __sanitizer_symbolize_pc(PC, "%p %F %L", PcDescr, sizeof(PcDescr)); + printf("guard: %p %x PC %s\n", guard, *guard, PcDescr); + } + +.. code-block:: c++ + + // trace-pc-guard-example.cc + void foo() { } + int main(int argc, char **argv) { + if (argc > 1) foo(); + } + +.. code-block:: console + + clang++ -g -fsanitize-coverage=trace-pc-guard trace-pc-guard-example.cc -c + clang++ trace-pc-guard-cb.cc trace-pc-guard-example.o -fsanitize=address + ASAN_OPTIONS=strip_path_prefix=`pwd`/ ./a.out + +.. code-block:: console + + INIT: 0x71bcd0 0x71bce0 + guard: 0x71bcd4 2 PC 0x4ecd5b in main trace-pc-guard-example.cc:2 + guard: 0x71bcd8 3 PC 0x4ecd9e in main trace-pc-guard-example.cc:3:7 + + Tracing data flow ================= -- 2.40.0