[compiler-rt] r293958 - [sanitizer] Use interception to access to strong definitions in the executable.

Marcos Pividori via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 2 15:02:11 PST 2017


Author: mpividori
Date: Thu Feb  2 17:02:11 2017
New Revision: 293958

URL: http://llvm.org/viewvc/llvm-project?rev=293958&view=rev
Log:
[sanitizer] Use interception to access to strong definitions in the executable.

In Windows, when sanitizers are implemented as a shared library (DLL), users can
redefine and export a new definition for weak functions, in the main executable,
for example:

extern "C" __declspec(dllexport)
void __sanitizer_cov_trace_pc_guard(u32* guard) {
  // Different implementation provided by the client.
}

However, other dlls, will continue using the default implementation imported
from the sanitizer dll. This is different in linux, where all the shared
libraries will consider the strong definition.

With the implementation in this diff, when the dll is initialized, it will check
if the main executable exports the definition for some weak function (for
example __sanitizer_cov_trace_pc_guard). If it finds that function, then it will
override the function in the dll with that pointer. So, all the dlls with
instrumentation that import __sanitizer_cov_trace_pc_guard__dll() from asan dll,
will be using the function provided by the main executable.

In other words, when the main executable exports a strong definition for a weak
function, we ensure all the dlls use that implementation instead of the default
weak implementation.

The behavior is similar to linux. Now, every user that want to override a weak
function, only has to define and export it. The same for Linux and Windows, and
it will work fine. So, there is no difference on the user's side.

All the sanitizers will include a file sanitizer_win_weak_interception.cc that
register sanitizer's weak functions to be intercepted in the binary section WEAK

When the sanitizer dll is initialized, it will execute weak_intercept_init()
which will consider all the CB registered in the section WEAK. So, for all the
weak functions registered, we will check if a strong definition is provided in
the main executable.

All the files sanitizer_win_weak_interception.cc are independent, so we do not
need to include a specific list of sanitizers.
Now, we include [asan|ubsan|sanitizer_coverage]_win_weak_interception.cc and
sanitizer_win_weak_interception.cc in asan dll, so when it is initialized, it
will consider all the weak functions from asan, ubsan and sanitizer coverage.

After this diff, sanitizer coverage is fixed for MD on Windows. In particular
libFuzzer can provide custom implementation for all sanitizer coverage's weak
functions, and they will be considered by asan dll.

Differential Revision: https://reviews.llvm.org/D29168

Added:
    compiler-rt/trunk/lib/asan/asan_win_weak_interception.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_win_weak_interception.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_weak_interception.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_weak_interception.h
    compiler-rt/trunk/lib/ubsan/ubsan_win_weak_interception.cc
Modified:
    compiler-rt/trunk/lib/asan/CMakeLists.txt
    compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
    compiler-rt/trunk/lib/ubsan/CMakeLists.txt

Modified: compiler-rt/trunk/lib/asan/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/CMakeLists.txt?rev=293958&r1=293957&r2=293958&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/asan/CMakeLists.txt Thu Feb  2 17:02:11 2017
@@ -176,6 +176,21 @@ else()
       set(VERSION_SCRIPT_FLAG)
     endif()
 
+    set(ASAN_DYNAMIC_WEAK_INTERCEPTION)
+    if (MSVC)
+      add_compiler_rt_object_libraries(AsanWeakInterception
+        ${SANITIZER_COMMON_SUPPORTED_OS}
+        ARCHS ${ASAN_SUPPORTED_ARCH}
+        SOURCES asan_win_weak_interception.cc
+        CFLAGS ${ASAN_CFLAGS} -DSANITIZER_DYNAMIC
+        DEFS ${ASAN_COMMON_DEFINITIONS})
+      set(ASAN_DYNAMIC_WEAK_INTERCEPTION
+          AsanWeakInterception
+          UbsanWeakInterception
+          SancovWeakInterception
+          SanitizerCommonWeakInterception)
+    endif()
+
     add_compiler_rt_runtime(clang_rt.asan
       SHARED
       ARCHS ${arch}
@@ -187,6 +202,7 @@ else()
               # add_dependencies(clang_rt.asan-dynamic-${arch} clang_rt.asan-dynamic-${arch}-version-list)
               RTAsan_dynamic_version_script_dummy
               RTUbsan_cxx
+              ${ASAN_DYNAMIC_WEAK_INTERCEPTION}
       CFLAGS ${ASAN_DYNAMIC_CFLAGS}
       LINK_FLAGS ${ASAN_DYNAMIC_LINK_FLAGS}
                 ${VERSION_SCRIPT_FLAG}

Added: compiler-rt/trunk/lib/asan/asan_win_weak_interception.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_win_weak_interception.cc?rev=293958&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_win_weak_interception.cc (added)
+++ compiler-rt/trunk/lib/asan/asan_win_weak_interception.cc Thu Feb  2 17:02:11 2017
@@ -0,0 +1,23 @@
+//===-- asan_win_weak_interception.cc -------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This module should be included in Address Sanitizer when it is implemented as
+// a shared library on Windows (dll), in order to delegate the calls of weak
+// functions to the implementation in the main executable when a strong
+// definition is provided.
+//===----------------------------------------------------------------------===//
+#ifdef SANITIZER_DYNAMIC
+#include "sanitizer_common/sanitizer_win_weak_interception.h"
+#include "asan_interface_internal.h"
+// Check if strong definitions for weak functions are present in the main
+// executable. If that is the case, override dll functions to point to strong
+// implementations.
+#define INTERFACE_FUNCTION(Name)
+#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
+#include "asan_interface.inc"
+#endif // SANITIZER_DYNAMIC

Modified: compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt?rev=293958&r1=293957&r2=293958&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt Thu Feb  2 17:02:11 2017
@@ -188,6 +188,19 @@ add_compiler_rt_object_libraries(RTSanit
   DEFS ${SANITIZER_COMMON_DEFINITIONS})
 
 if(MSVC)
+  add_compiler_rt_object_libraries(SanitizerCommonWeakInterception
+    ${SANITIZER_COMMON_SUPPORTED_OS}
+    ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH}
+    SOURCES sanitizer_win_weak_interception.cc
+    CFLAGS ${SANITIZER_CFLAGS} -DSANITIZER_DYNAMIC
+    DEFS ${SANITIZER_COMMON_DEFINITIONS})
+  add_compiler_rt_object_libraries(SancovWeakInterception
+    ${SANITIZER_COMMON_SUPPORTED_OS}
+    ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH}
+    SOURCES sanitizer_coverage_win_weak_interception.cc
+    CFLAGS ${SANITIZER_CFLAGS} -DSANITIZER_DYNAMIC
+    DEFS ${SANITIZER_COMMON_DEFINITIONS})
+
   add_compiler_rt_object_libraries(SanitizerCommonDllThunk
     ${SANITIZER_COMMON_SUPPORTED_OS}
     ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH}

Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_win_weak_interception.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_win_weak_interception.cc?rev=293958&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_win_weak_interception.cc (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_win_weak_interception.cc Thu Feb  2 17:02:11 2017
@@ -0,0 +1,24 @@
+//===-- sanitizer_coverage_win_weak_interception.cc -----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This module should be included in Sanitizer Coverage when it implemented as a
+// shared library on Windows (dll), in order to delegate the calls of weak
+// functions to the implementation in the main executable when a strong
+// definition is provided.
+//===----------------------------------------------------------------------===//
+#ifdef SANITIZER_DYNAMIC
+#include "sanitizer_win_weak_interception.h"
+#include "sanitizer_interface_internal.h"
+#include "sancov_flags.h"
+// Check if strong definitions for weak functions are present in the main
+// executable. If that is the case, override dll functions to point to strong
+// implementations.
+#define INTERFACE_FUNCTION(Name)
+#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
+#include "sanitizer_coverage_interface.inc"
+#endif // SANITIZER_DYNAMIC

Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_weak_interception.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_weak_interception.cc?rev=293958&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_weak_interception.cc (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_weak_interception.cc Thu Feb  2 17:02:11 2017
@@ -0,0 +1,82 @@
+//===-- sanitizer_win_weak_interception.cc --------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This module should be included in the sanitizer when it is implemented as a
+// shared library on Windows (dll), in order to delegate the calls of weak
+// functions to the implementation in the main executable when a strong
+// definition is provided.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_WINDOWS && SANITIZER_DYNAMIC
+#include "sanitizer_win_weak_interception.h"
+#include "sanitizer_allocator_interface.h"
+#include "sanitizer_interface_internal.h"
+#include "sanitizer_win_defs.h"
+#include "interception/interception.h"
+
+extern "C" {
+void *WINAPI GetModuleHandleA(const char *module_name);
+void abort();
+}
+
+namespace __sanitizer {
+// Try to get a pointer to real_function in the main module and override
+// dll_function with that pointer. If the function isn't found, nothing changes.
+int interceptWhenPossible(uptr dll_function, const char *real_function) {
+  uptr real = __interception::InternalGetProcAddress(
+      (void *)GetModuleHandleA(0), real_function);
+  if (real && !__interception::OverrideFunction((uptr)dll_function, real, 0))
+    abort();
+  return 0;
+}
+} // namespace __sanitizer
+
+// Include Sanitizer Common interface.
+#define INTERFACE_FUNCTION(Name)
+#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
+#include "sanitizer_common_interface.inc"
+
+#pragma section(".WEAK$A", read)  // NOLINT
+#pragma section(".WEAK$Z", read)  // NOLINT
+
+typedef void (*InterceptCB)();
+extern "C" {
+__declspec(allocate(".WEAK$A")) InterceptCB __start_weak_list;
+__declspec(allocate(".WEAK$Z")) InterceptCB __stop_weak_list;
+}
+
+static int weak_intercept_init() {
+  static bool flag = false;
+  // weak_interception_init is expected to be called by only one thread.
+  if (flag) return 0;
+  flag = true;
+
+  for (InterceptCB *it = &__start_weak_list; it < &__stop_weak_list; ++it)
+    if (*it)
+      (*it)();
+
+  // In DLLs, the callbacks are expected to return 0,
+  // otherwise CRT initialization fails.
+  return 0;
+}
+
+#pragma section(".CRT$XIB", long, read)  // NOLINT
+__declspec(allocate(".CRT$XIB")) int (*__weak_intercept_preinit)() =
+    weak_intercept_init;
+
+static void WINAPI weak_intercept_thread_init(void *mod, unsigned long reason,
+                                              void *reserved) {
+  if (reason == /*DLL_PROCESS_ATTACH=*/1) weak_intercept_init();
+}
+
+#pragma section(".CRT$XLAB", long, read)  // NOLINT
+__declspec(allocate(".CRT$XLAB")) void(WINAPI *__weak_intercept_tls_init)(
+    void *, unsigned long, void *) = weak_intercept_thread_init;
+
+#endif // SANITIZER_WINDOWS && SANITIZER_DYNAMIC

Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_weak_interception.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_weak_interception.h?rev=293958&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_weak_interception.h (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_weak_interception.h Thu Feb  2 17:02:11 2017
@@ -0,0 +1,33 @@
+//===-- sanitizer_win_weak_interception.h ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This header provide helper macros to delegate calls of weak functions to the
+// implementation in the main executable when a strong definition is present.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_WIN_WEAK_INTERCEPTION_H
+#define SANITIZER_WIN_WEAK_INTERCEPTION_H
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+int interceptWhenPossible(uptr dll_function, const char *real_function);
+}
+
+// ----------------- Function interception helper macros -------------------- //
+// Weak functions, could be redefined in the main executable, but that is not
+// necessary, so we shouldn't die if we can not find a reference.
+#define INTERCEPT_WEAK(Name) interceptWhenPossible((uptr) Name, #Name);
+
+#define INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)                                \
+  static int intercept_##Name() {                                              \
+    return __sanitizer::interceptWhenPossible((__sanitizer::uptr) Name, #Name);\
+  }                                                                            \
+  __pragma(section(".WEAK$M", long, read))                                     \
+  __declspec(allocate(".WEAK$M")) int (*__weak_intercept_##Name)() =           \
+      intercept_##Name;
+
+#endif // SANITIZER_WIN_WEAK_INTERCEPTION_H

Modified: compiler-rt/trunk/lib/ubsan/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/CMakeLists.txt?rev=293958&r1=293957&r2=293958&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/ubsan/CMakeLists.txt Thu Feb  2 17:02:11 2017
@@ -91,6 +91,13 @@ else()
     SOURCES ${UBSAN_CXX_SOURCES} CFLAGS ${UBSAN_CXXFLAGS})
 
   if (WIN32)
+    add_compiler_rt_object_libraries(UbsanWeakInterception
+      ${SANITIZER_COMMON_SUPPORTED_OS}
+      ARCHS ${UBSAN_SUPPORTED_ARCH}
+      SOURCES ubsan_win_weak_interception.cc
+      CFLAGS ${UBSAN_CFLAGS} -DSANITIZER_DYNAMIC
+      DEFS ${UBSAN_COMMON_DEFINITIONS})
+
     add_compiler_rt_object_libraries(UbsanDllThunk
       ${SANITIZER_COMMON_SUPPORTED_OS}
       ARCHS ${UBSAN_SUPPORTED_ARCH}

Added: compiler-rt/trunk/lib/ubsan/ubsan_win_weak_interception.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_win_weak_interception.cc?rev=293958&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_win_weak_interception.cc (added)
+++ compiler-rt/trunk/lib/ubsan/ubsan_win_weak_interception.cc Thu Feb  2 17:02:11 2017
@@ -0,0 +1,23 @@
+//===-- ubsan_win_weak_interception.cc ------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This module should be included in Ubsan when it is implemented as a shared
+// library on Windows (dll), in order to delegate the calls of weak functions to
+// the implementation in the main executable when a strong definition is
+// provided.
+//===----------------------------------------------------------------------===//
+#ifdef SANITIZER_DYNAMIC
+#include "sanitizer_common/sanitizer_win_weak_interception.h"
+#include "ubsan_flags.h"
+// Check if strong definitions for weak functions are present in the main
+// executable. If that is the case, override dll functions to point to strong
+// implementations.
+#define INTERFACE_FUNCTION(Name)
+#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
+#include "ubsan_interface.inc"
+#endif // SANITIZER_DYNAMIC




More information about the llvm-commits mailing list