summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEtienne Bergeron <etienneb@google.com>2016-09-19 15:59:01 +0000
committerEtienne Bergeron <etienneb@google.com>2016-09-19 15:59:01 +0000
commit96f3c80a994d3fe69f79e398b736a46801784524 (patch)
tree62061d345bd72c22d4692141e52de2f7726c171a
parent4b894fcf964a7203571795aec0ccef622f8c14d3 (diff)
[compiler-rt] Add support for the dynamic shadow allocation
Summary: This patch is adding the needed code to compiler-rt to support dynamic shadow. This is to support this patch: https://reviews.llvm.org/D23354 It's adding support for using a shadow placed at a dynamic address determined at runtime. The dynamic shadow is required to work on windows 64-bits. Reviewers: rnk, kcc, vitalybuka Subscribers: kubabrecka, dberris, llvm-commits, chrisha Differential Revision: https://reviews.llvm.org/D23363 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@281909 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/asan/asan_interface_internal.h7
-rw-r--r--lib/asan/asan_mapping.h3
-rw-r--r--lib/asan/asan_rtl.cc28
-rw-r--r--lib/asan/asan_win_dll_thunk.cc12
-rw-r--r--lib/asan/asan_win_dynamic_runtime_thunk.cc17
-rw-r--r--lib/sanitizer_common/sanitizer_common.h3
-rw-r--r--lib/sanitizer_common/sanitizer_posix.cc5
-rw-r--r--lib/sanitizer_common/sanitizer_win.cc20
8 files changed, 63 insertions, 32 deletions
diff --git a/lib/asan/asan_interface_internal.h b/lib/asan/asan_interface_internal.h
index f9a1eb5a2..da45cef22 100644
--- a/lib/asan/asan_interface_internal.h
+++ b/lib/asan/asan_interface_internal.h
@@ -31,6 +31,10 @@ extern "C" {
// before any instrumented code is executed and before any call to malloc.
SANITIZER_INTERFACE_ATTRIBUTE void __asan_init();
+ // This function should be called by a loaded instrumented module.
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_init_from_dll(
+ int *detect_stack_use_after_return, uptr *shadow_memory_dynamic_address);
+
// This function exists purely to get a linker/loader error when using
// incompatible versions of instrumentation and runtime library. Please note
// that __asan_version_mismatch_check is a macro that is replaced with
@@ -172,6 +176,9 @@ extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
/* OPTIONAL */ const char* __asan_default_options();
+ SANITIZER_INTERFACE_ATTRIBUTE
+ extern uptr __asan_shadow_memory_dynamic_address;
+
// Global flag, copy of ASAN_OPTIONS=detect_stack_use_after_return
SANITIZER_INTERFACE_ATTRIBUTE
extern int __asan_option_detect_stack_use_after_return;
diff --git a/lib/asan/asan_mapping.h b/lib/asan/asan_mapping.h
index 52c4f67a5..40ff54fd0 100644
--- a/lib/asan/asan_mapping.h
+++ b/lib/asan/asan_mapping.h
@@ -140,7 +140,6 @@ static const u64 kSystemZ_ShadowOffset64 = 1ULL << 52;
static const u64 kFreeBSD_ShadowOffset32 = 1ULL << 30; // 0x40000000
static const u64 kFreeBSD_ShadowOffset64 = 1ULL << 46; // 0x400000000000
static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000
-static const u64 kWindowsShadowOffset64 = 1ULL << 45; // 32TB
#define SHADOW_SCALE kDefaultShadowScale
@@ -183,7 +182,7 @@ static const u64 kWindowsShadowOffset64 = 1ULL << 45; // 32TB
# elif defined(__mips64)
# define SHADOW_OFFSET kMIPS64_ShadowOffset64
# elif SANITIZER_WINDOWS64
-# define SHADOW_OFFSET kWindowsShadowOffset64
+# define SHADOW_OFFSET __asan_shadow_memory_dynamic_address
# else
# define SHADOW_OFFSET kDefaultShort64bitShadowOffset
# endif
diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc
index 5a1128d6e..1d676bd0d 100644
--- a/lib/asan/asan_rtl.cc
+++ b/lib/asan/asan_rtl.cc
@@ -32,6 +32,7 @@
#include "ubsan/ubsan_init.h"
#include "ubsan/ubsan_platform.h"
+uptr __asan_shadow_memory_dynamic_address; // Global interface symbol.
int __asan_option_detect_stack_use_after_return; // Global interface symbol.
uptr *__asan_test_only_reported_buggy_pointer; // Used only for testing asan.
@@ -460,7 +461,20 @@ static void AsanInitInternal() {
ReplaceSystemMalloc();
+ __asan_shadow_memory_dynamic_address = 0;
uptr shadow_start = kLowShadowBeg;
+ if (shadow_start == 0) {
+ uptr granularity = GetMmapGranularity();
+ uptr alignment = 8 * granularity;
+ uptr left_padding = granularity;
+ uptr space_size = kHighShadowEnd + left_padding;
+
+ shadow_start = FindAvailableMemoryRange(space_size, alignment, granularity);
+ CHECK_NE((uptr)0, shadow_start);
+ CHECK(IsAligned(shadow_start, alignment));
+ }
+ __asan_shadow_memory_dynamic_address = shadow_start;
+
if (kLowShadowBeg)
shadow_start -= GetMmapGranularity();
bool full_shadow_is_available =
@@ -472,12 +486,6 @@ static void AsanInitInternal() {
kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;
kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0;
}
-#elif SANITIZER_WINDOWS64
- // Disable the "mid mem" shadow layout.
- if (!full_shadow_is_available) {
- kMidMemBeg = 0;
- kMidMemEnd = 0;
- }
#endif
if (Verbosity()) PrintAddressSpaceLayout();
@@ -650,6 +658,14 @@ void __asan_init() {
AsanInitInternal();
}
+// Called by a loaded DLL to initialize itself.
+void __asan_init_from_dll(int *detect_stack_use_after_return,
+ uptr *shadow_memory_dynamic_address) {
+ __asan_init();
+ *detect_stack_use_after_return = __asan_option_detect_stack_use_after_return;
+ *shadow_memory_dynamic_address = __asan_shadow_memory_dynamic_address;
+}
+
void __asan_version_mismatch_check() {
// Do nothing.
}
diff --git a/lib/asan/asan_win_dll_thunk.cc b/lib/asan/asan_win_dll_thunk.cc
index 4b8a08c5e..870286d54 100644
--- a/lib/asan/asan_win_dll_thunk.cc
+++ b/lib/asan/asan_win_dll_thunk.cc
@@ -199,23 +199,21 @@ static void InterceptHooks();
// ----------------- ASan own interface functions --------------------
// Don't use the INTERFACE_FUNCTION machinery for this function as we actually
// want to call it in the __asan_init interceptor.
-WRAP_W_V(__asan_should_detect_stack_use_after_return)
-
extern "C" {
int __asan_option_detect_stack_use_after_return;
+ uptr __asan_shadow_memory_dynamic_address;
// Manually wrap __asan_init as we need to initialize
// __asan_option_detect_stack_use_after_return afterwards.
void __asan_init() {
- typedef void (*fntype)();
+ typedef void (*fntype)(int*, uptr*);
static fntype fn = 0;
// __asan_init is expected to be called by only one thread.
if (fn) return;
- fn = (fntype)getRealProcAddressOrDie("__asan_init");
- fn();
- __asan_option_detect_stack_use_after_return =
- (__asan_should_detect_stack_use_after_return() != 0);
+ fn = (fntype)getRealProcAddressOrDie("__asan_init_from_dll");
+ fn(&__asan_option_detect_stack_use_after_return,
+ &__asan_shadow_memory_dynamic_address);
InterceptHooks();
}
diff --git a/lib/asan/asan_win_dynamic_runtime_thunk.cc b/lib/asan/asan_win_dynamic_runtime_thunk.cc
index c6e2a65a4..4dcd47e14 100644
--- a/lib/asan/asan_win_dynamic_runtime_thunk.cc
+++ b/lib/asan/asan_win_dynamic_runtime_thunk.cc
@@ -34,23 +34,6 @@
#pragma section(".CRT$XTY", long, read) // NOLINT
////////////////////////////////////////////////////////////////////////////////
-// Define a copy of __asan_option_detect_stack_use_after_return that should be
-// used when linking an MD runtime with a set of object files on Windows.
-//
-// The ASan MD runtime dllexports '__asan_option_detect_stack_use_after_return',
-// so normally we would just dllimport it. Unfortunately, the dllimport
-// attribute adds __imp_ prefix to the symbol name of a variable.
-// Since in general we don't know if a given TU is going to be used
-// with a MT or MD runtime and we don't want to use ugly __imp_ names on Windows
-// just to work around this issue, let's clone the variable that is constant
-// after initialization anyways.
-extern "C" {
-__declspec(dllimport) int __asan_should_detect_stack_use_after_return();
-int __asan_option_detect_stack_use_after_return =
- __asan_should_detect_stack_use_after_return();
-}
-
-////////////////////////////////////////////////////////////////////////////////
// For some reason, the MD CRT doesn't call the C/C++ terminators during on DLL
// unload or on exit. ASan relies on LLVM global_dtors to call
// __asan_unregister_globals on these events, which unfortunately doesn't work
diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h
index d0b983ccf..0dabfb0f2 100644
--- a/lib/sanitizer_common/sanitizer_common.h
+++ b/lib/sanitizer_common/sanitizer_common.h
@@ -98,6 +98,9 @@ void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type);
bool MprotectNoAccess(uptr addr, uptr size);
bool MprotectReadOnly(uptr addr, uptr size);
+// Find an available address space.
+uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding);
+
// Used to check if we can map shadow memory to a fixed location.
bool MemoryRangeIsAvailable(uptr range_start, uptr range_end);
void ReleaseMemoryToOS(uptr addr, uptr size);
diff --git a/lib/sanitizer_common/sanitizer_posix.cc b/lib/sanitizer_common/sanitizer_posix.cc
index c70d5a40c..e00f2a929 100644
--- a/lib/sanitizer_common/sanitizer_posix.cc
+++ b/lib/sanitizer_common/sanitizer_posix.cc
@@ -358,6 +358,11 @@ SignalContext SignalContext::Create(void *siginfo, void *context) {
return SignalContext(context, addr, pc, sp, bp, is_memory_access, write_flag);
}
+uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding) {
+ CHECK("FindAvailableMemoryRange is not available" && 0);
+ return 0;
+}
+
} // namespace __sanitizer
#endif // SANITIZER_POSIX
diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc
index 7555360c6..1fd79231d 100644
--- a/lib/sanitizer_common/sanitizer_win.cc
+++ b/lib/sanitizer_common/sanitizer_win.cc
@@ -249,6 +249,26 @@ void DontDumpShadowMemory(uptr addr, uptr length) {
// FIXME: add madvise-analog when we move to 64-bits.
}
+uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding) {
+ uptr address = 0;
+ while (true) {
+ MEMORY_BASIC_INFORMATION info;
+ if (!::VirtualQuery((void*)address, &info, sizeof(info)))
+ return 0;
+
+ if (info.State == MEM_FREE) {
+ uptr shadow_address = RoundUpTo((uptr)info.BaseAddress + left_padding,
+ alignment);
+ if (shadow_address + size < (uptr)info.BaseAddress + info.RegionSize)
+ return shadow_address;
+ }
+
+ // Move to the next region.
+ address = (uptr)info.BaseAddress + info.RegionSize;
+ }
+ return 0;
+}
+
bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
MEMORY_BASIC_INFORMATION mbi;
CHECK(VirtualQuery((void *)range_start, &mbi, sizeof(mbi)));