[compiler-rt] r222425 - [DFSan] Add flag to dump the labels when the program terminates.

Lorenzo Martignoni martignlo at google.com
Thu Nov 20 02:01:08 PST 2014


Author: martignlo
Date: Thu Nov 20 04:01:08 2014
New Revision: 222425

URL: http://llvm.org/viewvc/llvm-project?rev=222425&view=rev
Log:
[DFSan] Add flag to dump the labels when the program terminates.

Differential Revision: http://reviews.llvm.org/D6306


Added:
    compiler-rt/trunk/test/dfsan/dump_labels.c
Modified:
    compiler-rt/trunk/include/sanitizer/dfsan_interface.h
    compiler-rt/trunk/lib/dfsan/dfsan.cc
    compiler-rt/trunk/lib/dfsan/dfsan.h

Modified: compiler-rt/trunk/include/sanitizer/dfsan_interface.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/sanitizer/dfsan_interface.h?rev=222425&r1=222424&r2=222425&view=diff
==============================================================================
--- compiler-rt/trunk/include/sanitizer/dfsan_interface.h (original)
+++ compiler-rt/trunk/include/sanitizer/dfsan_interface.h Thu Nov 20 04:01:08 2014
@@ -85,6 +85,12 @@ size_t dfsan_get_label_count(void);
 /// callback executes.  Pass in NULL to remove any callback.
 void dfsan_set_write_callback(dfsan_write_callback_t labeled_write_callback);
 
+/// Writes the labels currently used by the program to the given file
+/// descriptor. The lines of the output have the following format:
+///
+/// <label> <parent label 1> <parent label 2> <label description if any>
+void dfsan_dump_labels(int fd);
+
 #ifdef __cplusplus
 }  // extern "C"
 

Modified: compiler-rt/trunk/lib/dfsan/dfsan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/dfsan/dfsan.cc?rev=222425&r1=222424&r2=222425&view=diff
==============================================================================
--- compiler-rt/trunk/lib/dfsan/dfsan.cc (original)
+++ compiler-rt/trunk/lib/dfsan/dfsan.cc Thu Nov 20 04:01:08 2014
@@ -74,6 +74,14 @@ static atomic_dfsan_label *union_table(d
   return &(*(dfsan_union_table_t *) kUnionTableAddr)[l1][l2];
 }
 
+// Checks we do not run out of labels.
+static void dfsan_check_label(dfsan_label label) {
+  if (label == kInitializingLabel) {
+    Report("FATAL: DataFlowSanitizer: out of labels\n");
+    Die();
+  }
+}
+
 // Resolves the union of two unequal labels.  Nonequality is a precondition for
 // this function (the instrumentation pass inlines the equality test).
 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
@@ -106,7 +114,7 @@ dfsan_label __dfsan_union(dfsan_label l1
     } else {
       label =
         atomic_fetch_add(&__dfsan_last_label, 1, memory_order_relaxed) + 1;
-      CHECK_NE(label, kInitializingLabel);
+      dfsan_check_label(label);
       __dfsan_label_info[label].l1 = l1;
       __dfsan_label_info[label].l2 = l2;
     }
@@ -169,7 +177,7 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE
 dfsan_label dfsan_create_label(const char *desc, void *userdata) {
   dfsan_label label =
     atomic_fetch_add(&__dfsan_last_label, 1, memory_order_relaxed) + 1;
-  CHECK_NE(label, kInitializingLabel);
+  dfsan_check_label(label);
   __dfsan_label_info[label].l1 = __dfsan_label_info[label].l2 = 0;
   __dfsan_label_info[label].desc = desc;
   __dfsan_label_info[label].userdata = userdata;
@@ -259,14 +267,50 @@ dfsan_get_label_count(void) {
   return static_cast<uptr>(max_label_allocated);
 }
 
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+dfsan_dump_labels(int fd) {
+  dfsan_label last_label =
+      atomic_load(&__dfsan_last_label, memory_order_relaxed);
+
+  for (uptr l = 1; l <= last_label; ++l) {
+    char buf[64];
+    internal_snprintf(buf, sizeof(buf), "%u %u %u ", l,
+                      __dfsan_label_info[l].l1, __dfsan_label_info[l].l2);
+    internal_write(fd, buf, internal_strlen(buf));
+    if (__dfsan_label_info[l].l1 == 0 && __dfsan_label_info[l].desc) {
+      internal_write(fd, __dfsan_label_info[l].desc,
+                     internal_strlen(__dfsan_label_info[l].desc));
+    }
+    internal_write(fd, "\n", 1);
+  }
+}
+
 static void InitializeFlags(Flags &f, const char *env) {
   f.warn_unimplemented = true;
   f.warn_nonzero_labels = false;
   f.strict_data_dependencies = true;
+  f.dump_labels_at_exit = "";
 
   ParseFlag(env, &f.warn_unimplemented, "warn_unimplemented", "");
   ParseFlag(env, &f.warn_nonzero_labels, "warn_nonzero_labels", "");
   ParseFlag(env, &f.strict_data_dependencies, "strict_data_dependencies", "");
+  ParseFlag(env, &f.dump_labels_at_exit, "dump_labels_at_exit", "");
+}
+
+static void dfsan_fini() {
+  if (internal_strcmp(flags().dump_labels_at_exit, "") != 0) {
+    fd_t fd = OpenFile(flags().dump_labels_at_exit, true /* write */);
+    if (fd == kInvalidFd) {
+      Report("WARNING: DataFlowSanitizer: unable to open output file %s\n",
+             flags().dump_labels_at_exit);
+      return;
+    }
+
+    Report("INFO: DataFlowSanitizer: dumping labels to %s\n",
+           flags().dump_labels_at_exit);
+    dfsan_dump_labels(fd);
+    internal_close(fd);
+  }
 }
 
 #ifdef DFSAN_NOLIBC
@@ -288,6 +332,13 @@ static void dfsan_init(int argc, char **
   InitializeFlags(flags(), GetEnv("DFSAN_OPTIONS"));
 
   InitializeInterceptors();
+
+  // Register the fini callback to run when the program terminates successfully
+  // or it is killed by the runtime.
+  Atexit(dfsan_fini);
+  SetDieCallback(dfsan_fini);
+
+  __dfsan_label_info[kInitializingLabel].desc = "<init label>";
 }
 
 #if !defined(DFSAN_NOLIBC) && SANITIZER_CAN_USE_PREINIT_ARRAY

Modified: compiler-rt/trunk/lib/dfsan/dfsan.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/dfsan/dfsan.h?rev=222425&r1=222424&r2=222425&view=diff
==============================================================================
--- compiler-rt/trunk/lib/dfsan/dfsan.h (original)
+++ compiler-rt/trunk/lib/dfsan/dfsan.h Thu Nov 20 04:01:08 2014
@@ -61,6 +61,8 @@ struct Flags {
   // comparison might be data-dependent on the content of the strings). This
   // applies only to the custom functions defined in 'custom.c'.
   bool strict_data_dependencies;
+  // The path of the file where to dump the labels when the program terminates.
+  const char* dump_labels_at_exit;
 };
 
 extern Flags flags_data;

Added: compiler-rt/trunk/test/dfsan/dump_labels.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/dfsan/dump_labels.c?rev=222425&view=auto
==============================================================================
--- compiler-rt/trunk/test/dfsan/dump_labels.c (added)
+++ compiler-rt/trunk/test/dfsan/dump_labels.c Thu Nov 20 04:01:08 2014
@@ -0,0 +1,69 @@
+// RUN: %clang_dfsan -m64 %s -o %t
+// RUN: DFSAN_OPTIONS=dump_labels_at_exit=/dev/stdout %run %t 2>&1 | FileCheck %s
+// RUN: DFSAN_OPTIONS=dump_labels_at_exit=/dev/stdout not %run %t c 2>&1 | FileCheck %s --check-prefix=CHECK-OOL
+// RUN: DFSAN_OPTIONS=dump_labels_at_exit=/dev/stdout not %run %t u 2>&1 | FileCheck %s --check-prefix=CHECK-OOL
+
+// Tests that labels are properly dumped at program termination.
+
+#include <sanitizer/dfsan_interface.h>
+#include <assert.h>
+#include <stdio.h>
+
+int main(int argc, char** argv) {
+  int i = 1;
+  dfsan_label i_label = dfsan_create_label("i", 0);
+  dfsan_set_label(i_label, &i, sizeof(i));
+
+  int j = 2;
+  dfsan_label j_label = dfsan_create_label("j", 0);
+  dfsan_set_label(j_label, &j, sizeof(j));
+
+  int k = 3;
+  dfsan_label k_label = dfsan_create_label("k", 0);
+  dfsan_set_label(k_label, &k, sizeof(k));
+
+  dfsan_label ij_label = dfsan_get_label(i + j);
+  dfsan_label ijk_label = dfsan_get_label(i + j + k);
+
+  fprintf(stderr, "i %d j %d k %d ij %d ijk %d\n", i_label, j_label, k_label,
+          ij_label, ijk_label);
+
+  // CHECK: 1 0 0 i
+  // CHECK: 2 0 0 j
+  // CHECK: 3 0 0 k
+  // CHECK: 4 1 2
+  // CHECK: 5 3 4
+
+  if (argc > 1) {
+    // Exhaust the labels.
+    unsigned long num_labels = 1 << (sizeof(dfsan_label) * 8);
+    for (unsigned long i =  ijk_label + 1; i < num_labels - 2; ++i) {
+      dfsan_label l = dfsan_create_label("l", 0);
+      assert(l == i);
+    }
+
+    // Consume the last available label.
+    dfsan_label l = dfsan_union(5, 6);
+    assert(l == num_labels - 2);
+
+    // Try to allocate another label (either explicitly or by unioning two
+    // existing labels), but expect a crash.
+    if (argv[1][0] == 'c') {
+      l = dfsan_create_label("l", 0);
+    } else {
+      l = dfsan_union(6, 7);
+    }
+
+    // CHECK-OOL: FATAL: DataFlowSanitizer: out of labels
+    // CHECK-OOL: 1 0 0 i
+    // CHECK-OOL: 2 0 0 j
+    // CHECK-OOL: 3 0 0 k
+    // CHECK-OOL: 4 1 2
+    // CHECK-OOL: 5 3 4
+    // CHECK-OOL: 6 0 0
+    // CHECK-OOL: 65534 5 6
+    // CHECK-OOL: 65535 0 0 <init label>
+  }
+
+  return 0;
+}





More information about the llvm-commits mailing list