summaryrefslogtreecommitdiff
path: root/lib/esan
diff options
context:
space:
mode:
authorSagar Thakur <sagar.thakur@imgtec.com>2016-10-06 09:58:11 +0000
committerSagar Thakur <sagar.thakur@imgtec.com>2016-10-06 09:58:11 +0000
commit44c27065e3eba69f1eec9b164d77b871046ad390 (patch)
tree207d42b896ce92afb3009ca18cf043af8470ef62 /lib/esan
parentf0ef378b41825b9cf37d23ea58c75d647e9f5bdc (diff)
[ESan][MIPS] Adds support for MIPS64
With this patch 12 out of 13 tests are passing. Reviewed by zhaoqin. Differential: D23799 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@283435 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/esan')
-rw-r--r--lib/esan/esan.cpp8
-rw-r--r--lib/esan/esan.h1
-rw-r--r--lib/esan/esan_linux.cpp2
-rw-r--r--lib/esan/esan_shadow.h131
4 files changed, 120 insertions, 22 deletions
diff --git a/lib/esan/esan.cpp b/lib/esan/esan.cpp
index 2fb77894d..09b530b66 100644
--- a/lib/esan/esan.cpp
+++ b/lib/esan/esan.cpp
@@ -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]);
diff --git a/lib/esan/esan.h b/lib/esan/esan.h
index 5a0dde627..e73b21e56 100644
--- a/lib/esan/esan.h
+++ b/lib/esan/esan.h
@@ -34,6 +34,7 @@ namespace __esan {
extern bool EsanIsInitialized;
extern bool EsanDuringInit;
+extern uptr VmaSize;
void initializeLibrary(ToolType Tool);
int finalizeLibrary();
diff --git a/lib/esan/esan_linux.cpp b/lib/esan/esan_linux.cpp
index aa961b661..014205ce0 100644
--- a/lib/esan/esan_linux.cpp
+++ b/lib/esan/esan_linux.cpp
@@ -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'.
diff --git a/lib/esan/esan_shadow.h b/lib/esan/esan_shadow.h
index f8f154ef7..72a919a19 100644
--- a/lib/esan/esan_shadow.h
+++ b/lib/esan/esan_shadow.h
@@ -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,6 +24,12 @@
namespace __esan {
+struct ApplicationRegion {
+ uptr Start;
+ uptr End;
+ bool ShadowMergedWithPrev;
+};
+
#if SANITIZER_LINUX && defined(__x86_64__)
// Linux x86_64
//
@@ -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 AppRegions[] = {
{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,59 @@ static const uptr MaxStackSize = (1ULL << 40) - 4096;
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;
+ };
+
void initialize(uptr ShadowScale) {
- static const uptr OffsetArray[3] = {
- 0x0000130000000000u,
- 0x0000220000000000u,
- 0x0000440000000000u,
+
+ const uptr OffsetArray40[3] = {
+ 0x0000001300000000u,
+ 0x0000002200000000u,
+ 0x0000004400000000u,
};
+
+ const uptr OffsetArray47[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 +231,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) {