summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc18
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h1
-rw-r--r--compiler-rt/test/msan/Linux/mincore.cc36
3 files changed, 55 insertions, 0 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 74b098c562e..d671de98144 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -5219,6 +5219,23 @@ INTERCEPTOR(int, pthread_setcanceltype, int type, int *oldtype) {
#define INIT_PTHREAD_SETCANCEL
#endif
+#if SANITIZER_INTERCEPT_MINCORE
+INTERCEPTOR(int, mincore, void *addr, uptr length, unsigned char *vec) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, mincore, addr, length, vec);
+ int res = REAL(mincore)(addr, length, vec);
+ if (res == 0) {
+ uptr page_size = GetPageSizeCached();
+ uptr vec_size = ((length + page_size - 1) & (~(page_size - 1))) / page_size;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, vec, vec_size);
+ }
+ return res;
+}
+#define INIT_MINCORE COMMON_INTERCEPT_FUNCTION(mincore);
+#else
+#define INIT_MINCORE
+#endif
+
static void InitializeCommonInterceptors() {
static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap();
@@ -5391,4 +5408,5 @@ static void InitializeCommonInterceptors() {
INIT_FOPENCOOKIE;
INIT_SEM;
INIT_PTHREAD_SETCANCEL;
+ INIT_MINCORE;
}
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
index 15461bfc578..cad63d20e72 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -258,6 +258,7 @@
#define SANITIZER_INTERCEPT_FOPENCOOKIE SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_SEM SI_LINUX || SI_FREEBSD
#define SANITIZER_INTERCEPT_PTHREAD_SETCANCEL SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_MINCORE SI_LINUX
#define SANITIZER_INTERCEPTOR_HOOKS SI_LINUX
diff --git a/compiler-rt/test/msan/Linux/mincore.cc b/compiler-rt/test/msan/Linux/mincore.cc
new file mode 100644
index 00000000000..35f5713d431
--- /dev/null
+++ b/compiler-rt/test/msan/Linux/mincore.cc
@@ -0,0 +1,36 @@
+// RUN: %clangxx_msan -std=c++11 -O0 %s -o %t && %run %t
+
+#include <assert.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sanitizer/msan_interface.h>
+
+int main(void) {
+ unsigned char vec[20];
+ int res;
+ size_t PS = sysconf(_SC_PAGESIZE);
+ void *addr = mmap(nullptr, 20 * PS, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+
+ __msan_poison(&vec, sizeof(vec));
+ res = mincore(addr, 10 * PS, vec);
+ assert(res == 0);
+ assert(__msan_test_shadow(vec, sizeof(vec)) == 10);
+
+ __msan_poison(&vec, sizeof(vec));
+ res = mincore(addr, 10 * PS + 42, vec);
+ assert(res == 0);
+ assert(__msan_test_shadow(vec, sizeof(vec)) == 11);
+
+ __msan_poison(&vec, sizeof(vec));
+ res = mincore(addr, 10 * PS - 1, vec);
+ assert(res == 0);
+ assert(__msan_test_shadow(vec, sizeof(vec)) == 10);
+
+ __msan_poison(&vec, sizeof(vec));
+ res = mincore(addr, 1, vec);
+ assert(res == 0);
+ assert(__msan_test_shadow(vec, sizeof(vec)) == 1);
+
+ return 0;
+}
OpenPOWER on IntegriCloud