From 5d167dae7dcd9452bfdb9b85278de1f6afda8718 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 26 Mar 2014 21:09:53 +0000 Subject: [PATCH] Add function to get the number of DFSan labels allocated. Expose the number of DFSan labels allocated by adding function dfsan_get_label_count(). Patch by Sam Kerner! Differential Revision: http://llvm-reviews.chandlerc.com/D3109 llvm-svn: 204854 --- .../include/sanitizer/dfsan_interface.h | 3 + compiler-rt/lib/dfsan/dfsan.cc | 8 ++ compiler-rt/lib/dfsan/done_abilist.txt | 2 + compiler-rt/test/dfsan/label_count.c | 75 +++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 compiler-rt/test/dfsan/label_count.c diff --git a/compiler-rt/include/sanitizer/dfsan_interface.h b/compiler-rt/include/sanitizer/dfsan_interface.h index f14d45a2b2a1..913e7f3d0ed8 100644 --- a/compiler-rt/include/sanitizer/dfsan_interface.h +++ b/compiler-rt/include/sanitizer/dfsan_interface.h @@ -74,6 +74,9 @@ int dfsan_has_label(dfsan_label label, dfsan_label elem); /// that label, else returns 0. dfsan_label dfsan_has_label_with_desc(dfsan_label label, const char *desc); +/// Returns the number of labels allocated. +size_t dfsan_get_label_count(void); + #ifdef __cplusplus } // extern "C" diff --git a/compiler-rt/lib/dfsan/dfsan.cc b/compiler-rt/lib/dfsan/dfsan.cc index 598d81c2b9d4..076ec58d43d8 100644 --- a/compiler-rt/lib/dfsan/dfsan.cc +++ b/compiler-rt/lib/dfsan/dfsan.cc @@ -230,6 +230,14 @@ dfsan_has_label_with_desc(dfsan_label label, const char *desc) { } } +extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr +dfsan_get_label_count(void) { + dfsan_label max_label_allocated = + atomic_load(&__dfsan_last_label, memory_order_relaxed); + + return static_cast(max_label_allocated); +} + static void InitializeFlags(Flags &f, const char *env) { f.warn_unimplemented = true; f.warn_nonzero_labels = false; diff --git a/compiler-rt/lib/dfsan/done_abilist.txt b/compiler-rt/lib/dfsan/done_abilist.txt index 51b8212be3d9..a5a7acaa3734 100644 --- a/compiler-rt/lib/dfsan/done_abilist.txt +++ b/compiler-rt/lib/dfsan/done_abilist.txt @@ -16,6 +16,8 @@ fun:dfsan_get_label=uninstrumented fun:dfsan_get_label=custom fun:dfsan_read_label=uninstrumented fun:dfsan_read_label=discard +fun:dfsan_get_label_count=uninstrumented +fun:dfsan_get_label_count=discard fun:dfsan_get_label_info=uninstrumented fun:dfsan_get_label_info=discard fun:dfsan_has_label=uninstrumented diff --git a/compiler-rt/test/dfsan/label_count.c b/compiler-rt/test/dfsan/label_count.c new file mode 100644 index 000000000000..5e368ca1beda --- /dev/null +++ b/compiler-rt/test/dfsan/label_count.c @@ -0,0 +1,75 @@ +// RUN: %clang_dfsan -DLIB -m64 -c %s -o %t.lib.o && \ +// RUN: %clang_dfsan -m64 -c %s -o %t.o && \ +// RUN: %clang_dfsan -m64 %t.lib.o %t.o -o %t.bin && \ +// RUN: %t.bin + +// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 -DLIB -c %s -o %t.lib.o && \ +// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 -c %s -o %t.o && \ +// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 %t.o %t.lib.o -o %t.bin && \ +// RUN: %t.bin + +#include +#include + +#ifdef LIB +// Compiling this file with and without LIB defined allows this file to be +// built as two separate translation units. This ensures that the code +// can not be optimized in a way that removes behavior we wish to test. For +// example, computing a value should cause labels to be allocated only if +// the computation is actually done. Putting the computation here prevents +// the compiler from optimizing away the computation (and labeling) that +// tests wish to verify. + +int add_in_separate_translation_unit(int a, int b) { + return a + b; +} + +int multiply_in_separate_translation_unit(int a, int b) { + return a * b; +} + +#else + +int add_in_separate_translation_unit(int i, int j); +int multiply_in_separate_translation_unit(int i, int j); + +int main(void) { + size_t label_count; + + // No labels allocated yet. + label_count = dfsan_get_label_count(); + assert(0 == label_count); + + int i = 1; + dfsan_label i_label = dfsan_create_label("i", 0); + dfsan_set_label(i_label, &i, sizeof(i)); + + // One label allocated for i. + label_count = dfsan_get_label_count(); + assert(1u == label_count); + + int j = 2; + dfsan_label j_label = dfsan_create_label("j", 0); + dfsan_set_label(j_label, &j, sizeof(j)); + + // Check that a new label was allocated for j. + label_count = dfsan_get_label_count(); + assert(2u == label_count); + + // Create a value that combines i and j. + int i_plus_j = add_in_separate_translation_unit(i, j); + + // Check that a label was created for the union of i and j. + label_count = dfsan_get_label_count(); + assert(3u == label_count); + + // Combine i and j in a different way. Check that the existing label is + // reused, and a new label is not created. + int j_times_i = multiply_in_separate_translation_unit(j, i); + label_count = dfsan_get_label_count(); + assert(3u == label_count); + assert(dfsan_get_label(i_plus_j) == dfsan_get_label(j_times_i)); + + return 0; +} +#endif // #ifdef LIB