[compiler-rt] r280795 - [ESan][MIPS] Adds support for MIPS64

Sagar Thakur via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 7 02:09:04 PDT 2016


Author: slthakur
Date: Wed Sep  7 04:09:03 2016
New Revision: 280795

URL: http://llvm.org/viewvc/llvm-project?rev=280795&view=rev
Log:
[ESan][MIPS] Adds support for MIPS64

With this patch 10 out of 13 tests are passing.

Following is the list of failing tests:

    struct-simple.cpp
    workingset-signal-posix.cpp
    mmap-shadow-conflict.c

Reviewed by bruening
Differential: D23799

Added:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_mips64.S
Modified:
    compiler-rt/trunk/cmake/config-ix.cmake
    compiler-rt/trunk/lib/esan/esan.cpp
    compiler-rt/trunk/lib/esan/esan.h
    compiler-rt/trunk/lib/esan/esan_linux.cpp
    compiler-rt/trunk/lib/esan/esan_shadow.h
    compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h
    compiler-rt/trunk/test/esan/TestCases/verbose-simple.c
    compiler-rt/trunk/test/esan/lit.cfg
    compiler-rt/trunk/test/lit.common.cfg

Modified: compiler-rt/trunk/cmake/config-ix.cmake
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/cmake/config-ix.cmake?rev=280795&r1=280794&r2=280795&view=diff
==============================================================================
--- compiler-rt/trunk/cmake/config-ix.cmake (original)
+++ compiler-rt/trunk/cmake/config-ix.cmake Wed Sep  7 04:09:03 2016
@@ -159,7 +159,7 @@ set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X8
     ${MIPS32} ${MIPS64} ${PPC64} ${S390X})
 set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64})
 set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64})
-set(ALL_ESAN_SUPPORTED_ARCH ${X86_64})
+set(ALL_ESAN_SUPPORTED_ARCH ${X86_64} ${MIPS64})
 set(ALL_SCUDO_SUPPORTED_ARCH ${X86_64})
 set(ALL_XRAY_SUPPORTED_ARCH ${X86_64})
 

Modified: compiler-rt/trunk/lib/esan/esan.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/esan/esan.cpp?rev=280795&r1=280794&r2=280795&view=diff
==============================================================================
--- compiler-rt/trunk/lib/esan/esan.cpp (original)
+++ compiler-rt/trunk/lib/esan/esan.cpp Wed Sep  7 04:09:03 2016
@@ -141,9 +141,17 @@ static bool verifyShadowScheme() {
 }
 #endif
 
+uptr VmaSize;
+
 static void initializeShadow() {
   verifyAddressSpace();
 
+  // This is based on the assumption that the intial stack is always allocated
+  // in the topmost segment of the user address space and the assumption
+  // holds true on all the platforms currently supported.
+  VmaSize =
+    (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1);
+
   DCHECK(verifyShadowScheme());
 
   Mapping.initialize(ShadowScale[__esan_which_tool]);

Modified: compiler-rt/trunk/lib/esan/esan.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/esan/esan.h?rev=280795&r1=280794&r2=280795&view=diff
==============================================================================
--- compiler-rt/trunk/lib/esan/esan.h (original)
+++ compiler-rt/trunk/lib/esan/esan.h Wed Sep  7 04:09:03 2016
@@ -34,6 +34,7 @@ namespace __esan {
 
 extern bool EsanIsInitialized;
 extern bool EsanDuringInit;
+extern uptr VmaSize;
 
 void initializeLibrary(ToolType Tool);
 int finalizeLibrary();

Modified: compiler-rt/trunk/lib/esan/esan_linux.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/esan/esan_linux.cpp?rev=280795&r1=280794&r2=280795&view=diff
==============================================================================
--- compiler-rt/trunk/lib/esan/esan_linux.cpp (original)
+++ compiler-rt/trunk/lib/esan/esan_linux.cpp Wed Sep  7 04:09:03 2016
@@ -25,7 +25,7 @@
 namespace __esan {
 
 void verifyAddressSpace() {
-#if SANITIZER_LINUX && defined(__x86_64__)
+#if SANITIZER_LINUX && (defined(__x86_64__) || SANITIZER_MIPS64)
   // The kernel determines its mmap base from the stack size limit.
   // Our Linux 64-bit shadow mapping assumes the stack limit is less than a
   // terabyte, which keeps the mmap region above 0x7e00'.

Modified: compiler-rt/trunk/lib/esan/esan_shadow.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/esan/esan_shadow.h?rev=280795&r1=280794&r2=280795&view=diff
==============================================================================
--- compiler-rt/trunk/lib/esan/esan_shadow.h (original)
+++ compiler-rt/trunk/lib/esan/esan_shadow.h Wed Sep  7 04:09:03 2016
@@ -15,6 +15,7 @@
 #ifndef ESAN_SHADOW_H
 #define ESAN_SHADOW_H
 
+#include "esan.h"
 #include <sanitizer_common/sanitizer_platform.h>
 
 #if SANITIZER_WORDSIZE != 64
@@ -23,7 +24,13 @@
 
 namespace __esan {
 
-#if SANITIZER_LINUX && defined(__x86_64__)
+struct ApplicationRegion {
+  uptr Start;
+  uptr End;
+  bool ShadowMergedWithPrev;
+};
+
+#if SANITIZER_LINUX && defined(__x86_64__) 
 // Linux x86_64
 //
 // Application memory falls into these 5 regions (ignoring the corner case
@@ -89,12 +96,6 @@ namespace __esan {
 // [0x000015ff'ff601000, 0x00001600'00000000]
 // [0x000015ff'ff600000, 0x000015ff'ff601000]
 
-struct ApplicationRegion {
-  uptr Start;
-  uptr End;
-  bool ShadowMergedWithPrev;
-};
-
 static const struct ApplicationRegion AppRegions[] = {
   {0x0000000000000000ull, 0x0000010000000000u, false},
   {0x0000550000000000u,   0x0000570000000000u, false},
@@ -105,6 +106,52 @@ static const struct ApplicationRegion Ap
   {0x00007fffff601000u,   0x0000800000000000u, true},
   {0xffffffffff600000u,   0xffffffffff601000u, true},
 };
+
+#elif SANITIZER_LINUX && SANITIZER_MIPS64
+
+// Application memory falls into these 3 regions
+//
+// [0x00000001'00000000, 0x00000002'00000000) non-PIE + heap
+// [0x000000aa'00000000, 0x000000ab'00000000) PIE
+// [0x000000ff'00000000, 0x000000ff'ffffffff) libraries + stack
+//
+// This formula translates from application memory to shadow memory:
+//
+//   shadow(app) = ((app & 0x00000f'ffffffff) + offset) >> scale
+//
+// Where the offset for 1:1 is 0x000013'00000000.  For other scales, the
+// offset is shifted left by the scale, except for scales of 1 and 2 where
+// it must be tweaked in order to pass the double-shadow test
+// (see the "shadow(shadow)" comments below):
+//   scale == 0: 0x000013'00000000
+//   scale == 1: 0x000022'00000000
+//   scale == 2: 0x000044'00000000
+//   scale >= 3: (0x000013'00000000 << scale)
+//
+// The resulting shadow memory regions for a 0 scaling are:
+//
+// [0x00000014'00000000, 0x00000015'00000000)
+// [0x0000001d'00000000, 0x0000001e'00000000)
+// [0x00000022'00000000, 0x00000022'ffffffff)
+//
+// We also want to ensure that a wild access by the application into the shadow
+// regions will not corrupt our own shadow memory. shadow(shadow) ends up
+// disjoint from shadow(app):
+//
+// [0x00000017'00000000, 0x00000018'00000000)
+// [0x00000020'00000000, 0x00000021'00000000)
+// [0x00000015'00000000, 0x00000015'ffffffff]
+
+static const struct ApplicationRegion AppRegions[] = {
+  {0x0100000000u, 0x0200000000u, false},
+  {0xaa00000000u, 0xab00000000u, false},
+  {0xff00000000u, 0xffffffffffu, false},
+};
+
+#else
+#error Platform not supported
+#endif
+
 static const u32 NumAppRegions = sizeof(AppRegions)/sizeof(AppRegions[0]);
 
 // See the comment above: we do not currently support a stack size rlimit
@@ -113,29 +160,58 @@ static const uptr MaxStackSize = (1ULL <
 
 class ShadowMapping {
 public:
-  static const uptr Mask = 0x00000fffffffffffu;
+
   // The scale and offset vary by tool.
   uptr Scale;
   uptr Offset;
+
+  // TODO(sagar.thakur): Try to hardcode the mask as done in the compiler
+  // instrumentation to reduce the runtime cost of appToShadow.
+  struct ShadowMemoryMask40 { 
+    static const uptr Mask = 0x0000000fffffffffu;
+  };
+
+  struct ShadowMemoryMask47 {
+    static const uptr Mask = 0x00000fffffffffffu;
+  };
+
+  const uptr OffsetArray40[3] = {
+    0x0000001300000000u,
+    0x0000002200000000u,
+    0x0000004400000000u,
+  };
+
+  const uptr OffsetArray47[3] = {
+    0x0000130000000000u,
+    0x0000220000000000u,
+    0x0000440000000000u,
+  };
+
   void initialize(uptr ShadowScale) {
-    static const uptr OffsetArray[3] = {
-        0x0000130000000000u,
-        0x0000220000000000u,
-        0x0000440000000000u,
-    };
     Scale = ShadowScale;
-    if (Scale <= 2)
-      Offset = OffsetArray[Scale];
-    else
-      Offset = OffsetArray[0] << Scale;
+    switch (VmaSize) {
+      case 40: {
+        if (Scale <= 2)
+          Offset = OffsetArray40[Scale];
+        else
+          Offset = OffsetArray40[0] << Scale;
+      }
+      break;
+      case 47: {
+        if (Scale <= 2)
+          Offset = OffsetArray47[Scale];
+        else
+          Offset = OffsetArray47[0] << Scale;
+      }
+      break;
+      default: {
+        Printf("ERROR: %d-bit virtual memory address size not supported\n", VmaSize);
+        Die();
+      }
+    }
   }
 };
 extern ShadowMapping Mapping;
-#else
-// We'll want to use templatized functions over the ShadowMapping once
-// we support more platforms.
-#error Platform not supported
-#endif
 
 static inline bool getAppRegion(u32 i, uptr *Start, uptr *End) {
   if (i >= NumAppRegions)
@@ -154,9 +230,21 @@ bool isAppMem(uptr Mem) {
   return false;
 }
 
+template<typename Params>
+uptr appToShadowImpl(uptr App) {
+  return (((App & Params::Mask) + Mapping.Offset) >> Mapping.Scale);
+}
+
 ALWAYS_INLINE
 uptr appToShadow(uptr App) {
-  return (((App & ShadowMapping::Mask) + Mapping.Offset) >> Mapping.Scale);
+  switch (VmaSize) {
+    case 40: return appToShadowImpl<ShadowMapping::ShadowMemoryMask40>(App);
+    case 47: return appToShadowImpl<ShadowMapping::ShadowMemoryMask47>(App);
+    default: {
+      Printf("ERROR: %d-bit virtual memory address size not supported\n", VmaSize);
+      Die();
+    }
+  }
 }
 
 static inline bool getShadowRegion(u32 i, uptr *Start, uptr *End) {

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=280795&r1=280794&r2=280795&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt Wed Sep  7 04:09:03 2016
@@ -37,6 +37,8 @@ set(SANITIZER_SOURCES_NOTERMINATION
 if(UNIX AND NOT APPLE)
   list(APPEND SANITIZER_SOURCES_NOTERMINATION
     sanitizer_linux_x86_64.S)
+  list(APPEND SANITIZER_SOURCES_NOTERMINATION
+    sanitizer_linux_mips64.S)  
 endif()
 
 set(SANITIZER_SOURCES
@@ -147,6 +149,8 @@ if (LLVM_ENABLE_PEDANTIC AND UNIX AND NO
   # CMAKE_C*_FLAGS and re-add as a source property to all the non-.S files).
   set_source_files_properties(sanitizer_linux_x86_64.S
     PROPERTIES COMPILE_FLAGS "-w")
+  set_source_files_properties(sanitizer_linux_mips64.S
+    PROPERTIES COMPILE_FLAGS "-w")
 endif ()
 
 if(APPLE)

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=280795&r1=280794&r2=280795&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc Wed Sep  7 04:09:03 2016
@@ -99,7 +99,7 @@ const int FUTEX_WAKE = 1;
 # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
 #endif
 
-#if defined(__x86_64__)
+#if defined(__x86_64__) || SANITIZER_MIPS64
 extern "C" {
 extern void internal_sigreturn();
 }
@@ -671,7 +671,7 @@ int internal_sigaction_norestorer(int si
 // Invokes sigaction via a raw syscall with a restorer, but does not support
 // all platforms yet.
 // We disable for Go simply because we have not yet added to buildgo.sh.
-#if defined(__x86_64__) && !SANITIZER_GO
+#if (defined(__x86_64__) || SANITIZER_MIPS64) && !SANITIZER_GO
 int internal_sigaction_syscall(int signum, const void *act, void *oldact) {
   if (act == nullptr)
     return internal_sigaction_norestorer(signum, act, oldact);

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h?rev=280795&r1=280794&r2=280795&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h Wed Sep  7 04:09:03 2016
@@ -42,7 +42,7 @@ uptr internal_prctl(int option, uptr arg
 // (like the process-wide error reporting SEGV handler) must use
 // internal_sigaction instead.
 int internal_sigaction_norestorer(int signum, const void *act, void *oldact);
-#if defined(__x86_64__) && !SANITIZER_GO
+#if (defined(__x86_64__) || SANITIZER_MIPS64) && !SANITIZER_GO
 // Uses a raw system call to avoid interceptors.
 int internal_sigaction_syscall(int signum, const void *act, void *oldact);
 #endif

Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_mips64.S
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_mips64.S?rev=280795&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_mips64.S (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_mips64.S Wed Sep  7 04:09:03 2016
@@ -0,0 +1,23 @@
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+
+// Avoid being marked as needing an executable stack:
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
+
+// Further contents are mips64 only:
+#if defined(__linux__) && defined(__mips64)
+
+.section .text
+.set noreorder
+.globl internal_sigreturn
+.type internal_sigreturn, @function
+internal_sigreturn:
+
+        li $v0,5211 // #5211 is for SYS_rt_sigreturn
+        syscall
+
+.size internal_sigreturn, .-internal_sigreturn
+
+#endif // defined(__linux__) && defined(__mips64)

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h?rev=280795&r1=280794&r2=280795&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h Wed Sep  7 04:09:03 2016
@@ -617,13 +617,21 @@ namespace __sanitizer {
 
   // Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
   struct __sanitizer_kernel_sigaction_t {
+#if SANITIZER_MIPS
+    unsigned long sa_flags;
+#endif
     union {
       void (*handler)(int signo);
       void (*sigaction)(int signo, void *info, void *ctx);
     };
+#if !SANITIZER_MIPS
     unsigned long sa_flags;
     void (*sa_restorer)(void);
+#endif
     __sanitizer_kernel_sigset_t sa_mask;
+#if SANITIZER_MIPS
+    void (*sa_restorer)(void);
+#endif
   };
 
   extern uptr sig_ign;

Modified: compiler-rt/trunk/test/esan/TestCases/verbose-simple.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/esan/TestCases/verbose-simple.c?rev=280795&r1=280794&r2=280795&view=diff
==============================================================================
--- compiler-rt/trunk/test/esan/TestCases/verbose-simple.c (original)
+++ compiler-rt/trunk/test/esan/TestCases/verbose-simple.c Wed Sep  7 04:09:03 2016
@@ -1,14 +1,18 @@
 // RUN: %clang_esan_frag -O0 %s -o %t 2>&1
-// RUN: %env_esan_opts="verbosity=1 log_exe_name=1" %run %t 2>&1 | FileCheck %s
+// RUN: %env_esan_opts="verbosity=1 log_exe_name=1" %run %t 2>&1 | FileCheck --check-prefix=CHECK-%arch %s
 
 int main(int argc, char **argv) {
   // CHECK:      in esan::initializeLibrary
   // (There can be a re-exec for stack limit here.)
-  // CHECK:      Shadow scale=2 offset=0x440000000000
-  // CHECK-NEXT: Shadow #0: [110000000000-114000000000) (256GB)
-  // CHECK-NEXT: Shadow #1: [124000000000-12c000000000) (512GB)
-  // CHECK-NEXT: Shadow #2: [148000000000-150000000000) (512GB)
-  // CHECK-NEXT: in esan::finalizeLibrary
-  // CHECK-NEXT: ==verbose-simple{{.*}}EfficiencySanitizer: total struct field access count = 0
+  // CHECK-x86_64: Shadow scale=2 offset=0x440000000000
+  // CHECK-x86_64: Shadow #0: [110000000000-114000000000) (256GB)
+  // CHECK-x86_64: Shadow #1: [124000000000-12c000000000) (512GB)
+  // CHECK-x86_64: Shadow #2: [148000000000-150000000000) (512GB)
+  // CHECK-mips64: Shadow scale=2 offset=0x4400000000
+  // CHECK-mips64: Shadow #0: [1140000000-1180000000) (1GB)
+  // CHECK-mips64: Shadow #1: [1380000000-13c0000000) (1GB)
+  // CHECK-mips64: Shadow #2: [14c0000000-1500000000) (1GB)
+  // CHECK: in esan::finalizeLibrary
+  // CHECK: ==verbose-simple{{.*}}EfficiencySanitizer: total struct field access count = 0
   return 0;
 }

Modified: compiler-rt/trunk/test/esan/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/esan/lit.cfg?rev=280795&r1=280794&r2=280795&view=diff
==============================================================================
--- compiler-rt/trunk/test/esan/lit.cfg (original)
+++ compiler-rt/trunk/test/esan/lit.cfg Wed Sep  7 04:09:03 2016
@@ -40,5 +40,5 @@ config.substitutions.append(('%env_esan_
 config.suffixes = ['.c', '.cpp']
 
 # EfficiencySanitizer tests are currently supported on Linux x86-64 only.
-if config.host_os not in ['Linux'] or config.target_arch != 'x86_64':
+if config.host_os not in ['Linux'] or config.target_arch not in ['x86_64', 'mips64'] :
   config.unsupported = True

Modified: compiler-rt/trunk/test/lit.common.cfg
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/lit.common.cfg?rev=280795&r1=280794&r2=280795&view=diff
==============================================================================
--- compiler-rt/trunk/test/lit.common.cfg (original)
+++ compiler-rt/trunk/test/lit.common.cfg Wed Sep  7 04:09:03 2016
@@ -88,6 +88,9 @@ config.substitutions.append( ('%run', co
 # Define CHECK-%os to check for OS-dependent output.
 config.substitutions.append( ('CHECK-%os', ("CHECK-" + config.host_os)))
 
+# Define CHECK-%arch to check for architecture-dependent output.
+config.substitutions.append( ('CHECK-%arch', ("CHECK-" + config.host_arch)))
+
 if config.host_os == 'Windows':
   # FIXME: This isn't quite right. Specifically, it will succeed if the program
   # does not crash but exits with a non-zero exit code. We ought to merge




More information about the llvm-commits mailing list