[compiler-rt] r210098 - [sancov] Fix map update logic on Android.

Evgeniy Stepanov eugeni.stepanov at gmail.com
Tue Jun 3 05:15:43 PDT 2014


Author: eugenis
Date: Tue Jun  3 07:15:43 2014
New Revision: 210098

URL: http://llvm.org/viewvc/llvm-project?rev=210098&view=rev
Log:
[sancov] Fix map update logic on Android.

dlopen()/dlclose() are not interceptable on Android,
so we update .sancov.map in module constructor callbacks.

Added:
    compiler-rt/trunk/test/asan/TestCases/Android/
    compiler-rt/trunk/test/asan/TestCases/Android/coverage.cc   (with props)
    compiler-rt/trunk/test/asan/TestCases/Android/lit.local.cfg
Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc?rev=210098&r1=210097&r2=210098&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc Tue Jun  3 07:15:43 2014
@@ -146,6 +146,12 @@ void CoverageData::Extend(uptr npcs) {
   }
 
   atomic_store(&pc_array_size, size, memory_order_release);
+
+  if (SANITIZER_ANDROID) {
+    // dlopen/dlclose interceptors do not work on Android, so we rely on
+    // Extend() calls to update .sancov.map.
+    CovUpdateMapping();
+  }
 }
 
 // Simply add the pc into the vector under lock. If the function is called more

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc?rev=210098&r1=210097&r2=210098&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc Tue Jun  3 07:15:43 2014
@@ -37,22 +37,16 @@ namespace __sanitizer {
 
 static const uptr kMaxNumberOfModules = 1 << 14;
 
+static char *last_mapping;
+static StaticSpinMutex mapping_mu;
+
 void CovUpdateMapping() {
   if (!common_flags()->coverage || !common_flags()->coverage_direct) return;
 
-  int err;
-  InternalScopedString tmp_path(64 +
-                                internal_strlen(common_flags()->coverage_dir));
-  uptr res = internal_snprintf((char *)tmp_path.data(), tmp_path.size(),
-                    "%s/%zd.sancov.map.tmp", common_flags()->coverage_dir,
-                    internal_getpid());
-  CHECK_LE(res, tmp_path.size());
-  uptr map_fd = OpenFile(tmp_path.data(), true);
-  if (internal_iserror(map_fd)) {
-    Report(" Coverage: failed to open %s for writing\n", tmp_path.data());
-    Die();
-  }
+  SpinMutexLock l(&mapping_mu);
 
+  const uptr kMaxTextSize = 64 * 1024;
+  InternalScopedString text(kMaxTextSize);
   InternalScopedBuffer<char> modules_data(kMaxNumberOfModules *
                                           sizeof(LoadedModule));
   LoadedModule *modules = (LoadedModule *)modules_data.data();
@@ -60,31 +54,40 @@ void CovUpdateMapping() {
   int n_modules = GetListOfModules(modules, kMaxNumberOfModules,
                                    /* filter */ 0);
 
-  InternalScopedString line(4096);
-  line.append("%d\n", sizeof(uptr) * 8);
-  res = internal_write(map_fd, line.data(), line.length());
-  if (internal_iserror(res, &err)) {
-    Printf("sancov.map write failed: %d\n", err);
-    Die();
-  }
-  line.clear();
-
+  text.append("%d\n", sizeof(uptr) * 8);
   for (int i = 0; i < n_modules; ++i) {
     char *module_name = StripModuleName(modules[i].full_name());
     for (unsigned j = 0; j < modules[i].n_ranges(); ++j) {
-      line.append("%zx %zx %zx %s\n", modules[i].address_range_start(j),
+      text.append("%zx %zx %zx %s\n", modules[i].address_range_start(j),
                   modules[i].address_range_end(j), modules[i].base_address(),
                   module_name);
-      res = internal_write(map_fd, line.data(), line.length());
-      if (internal_iserror(res, &err)) {
-        Printf("sancov.map write failed: %d\n", err);
-        Die();
-      }
-      line.clear();
     }
     InternalFree(module_name);
   }
 
+  // Do not write mapping if it is the same as the one we've wrote last time.
+  if (last_mapping && (internal_strcmp(last_mapping, text.data()) == 0)) return;
+  if (!last_mapping) last_mapping = (char *)InternalAlloc(kMaxTextSize);
+  internal_strncpy(last_mapping, text.data(), kMaxTextSize);
+
+  int err;
+  InternalScopedString tmp_path(64 +
+                                internal_strlen(common_flags()->coverage_dir));
+  uptr res = internal_snprintf((char *)tmp_path.data(), tmp_path.size(),
+                    "%s/%zd.sancov.map.tmp", common_flags()->coverage_dir,
+                    internal_getpid());
+  CHECK_LE(res, tmp_path.size());
+  uptr map_fd = OpenFile(tmp_path.data(), true);
+  if (internal_iserror(map_fd)) {
+    Report(" Coverage: failed to open %s for writing\n", tmp_path.data());
+    Die();
+  }
+
+  res = internal_write(map_fd, text.data(), text.length());
+  if (internal_iserror(res, &err)) {
+    Printf("sancov.map write failed: %d\n", err);
+    Die();
+  }
   internal_close(map_fd);
 
   InternalScopedString path(64 + internal_strlen(common_flags()->coverage_dir));

Added: compiler-rt/trunk/test/asan/TestCases/Android/coverage.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Android/coverage.cc?rev=210098&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Android/coverage.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Android/coverage.cc Tue Jun  3 07:15:43 2014
@@ -0,0 +1,41 @@
+// Test for direct coverage writing with dlopen.
+// RUN: %clangxx_asan -mllvm -asan-coverage=1 -DSHARED %s -shared -o %T/libcoverage_direct_test_1.so -fPIC
+// RUN: %clangxx_asan -mllvm -asan-coverage=1 -DSO_DIR=\"%device\" %s -o %t
+
+// RUN: adb shell rm -rf %device/coverage-direct
+// RUN: rm -rf %T/coverage-direct
+
+// RUN: adb shell mkdir -p %device/coverage-direct/direct
+// RUN: mkdir -p %T/coverage-direct/direct
+// RUN: ASAN_OPTIONS=coverage=1:coverage_direct=1:coverage_dir=%device/coverage-direct/direct:verbosity=1 %run %t
+// RUN: adb pull %device/coverage-direct/direct %T/coverage-direct/direct
+// RUN: ls; pwd
+// RUN: cd %T/coverage-direct/direct
+// RUN: %sancov rawunpack *.sancov.raw
+// RUN: %sancov print *.sancov |& FileCheck %s
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#ifdef SHARED
+extern "C" {
+void bar() { printf("bar\n"); }
+}
+#else
+
+int main(int argc, char **argv) {
+  fprintf(stderr, "PID: %d\n", getpid());
+  void *handle1 =
+      dlopen(SO_DIR "/libcoverage_direct_test_1.so", RTLD_LAZY);
+  assert(handle1);
+  void (*bar1)() = (void (*)())dlsym(handle1, "bar");
+  assert(bar1);
+  bar1();
+
+  return 0;
+}
+#endif
+
+// CHECK: 2 PCs total

Propchange: compiler-rt/trunk/test/asan/TestCases/Android/coverage.cc
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: compiler-rt/trunk/test/asan/TestCases/Android/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Android/lit.local.cfg?rev=210098&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Android/lit.local.cfg (added)
+++ compiler-rt/trunk/test/asan/TestCases/Android/lit.local.cfg Tue Jun  3 07:15:43 2014
@@ -0,0 +1,11 @@
+def getRoot(config):
+  if not config.parent:
+    return config
+  return getRoot(config.parent)
+
+root = getRoot(config)
+
+if root.android != "TRUE":
+  config.unsupported = True
+
+config.substitutions.append( ("%device", "/data/local/tmp/Output") )





More information about the llvm-commits mailing list