Skip to content
This repository was archived by the owner on May 21, 2019. It is now read-only.

Commit 96f3c80

Browse files
committed
[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
1 parent 4b894fc commit 96f3c80

File tree

8 files changed

+63
-32
lines changed

8 files changed

+63
-32
lines changed

lib/asan/asan_interface_internal.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ extern "C" {
3131
// before any instrumented code is executed and before any call to malloc.
3232
SANITIZER_INTERFACE_ATTRIBUTE void __asan_init();
3333

34+
// This function should be called by a loaded instrumented module.
35+
SANITIZER_INTERFACE_ATTRIBUTE void __asan_init_from_dll(
36+
int *detect_stack_use_after_return, uptr *shadow_memory_dynamic_address);
37+
3438
// This function exists purely to get a linker/loader error when using
3539
// incompatible versions of instrumentation and runtime library. Please note
3640
// that __asan_version_mismatch_check is a macro that is replaced with
@@ -172,6 +176,9 @@ extern "C" {
172176
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
173177
/* OPTIONAL */ const char* __asan_default_options();
174178

179+
SANITIZER_INTERFACE_ATTRIBUTE
180+
extern uptr __asan_shadow_memory_dynamic_address;
181+
175182
// Global flag, copy of ASAN_OPTIONS=detect_stack_use_after_return
176183
SANITIZER_INTERFACE_ATTRIBUTE
177184
extern int __asan_option_detect_stack_use_after_return;

lib/asan/asan_mapping.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,6 @@ static const u64 kSystemZ_ShadowOffset64 = 1ULL << 52;
140140
static const u64 kFreeBSD_ShadowOffset32 = 1ULL << 30; // 0x40000000
141141
static const u64 kFreeBSD_ShadowOffset64 = 1ULL << 46; // 0x400000000000
142142
static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000
143-
static const u64 kWindowsShadowOffset64 = 1ULL << 45; // 32TB
144143

145144
#define SHADOW_SCALE kDefaultShadowScale
146145

@@ -183,7 +182,7 @@ static const u64 kWindowsShadowOffset64 = 1ULL << 45; // 32TB
183182
# elif defined(__mips64)
184183
# define SHADOW_OFFSET kMIPS64_ShadowOffset64
185184
# elif SANITIZER_WINDOWS64
186-
# define SHADOW_OFFSET kWindowsShadowOffset64
185+
# define SHADOW_OFFSET __asan_shadow_memory_dynamic_address
187186
# else
188187
# define SHADOW_OFFSET kDefaultShort64bitShadowOffset
189188
# endif

lib/asan/asan_rtl.cc

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "ubsan/ubsan_init.h"
3333
#include "ubsan/ubsan_platform.h"
3434

35+
uptr __asan_shadow_memory_dynamic_address; // Global interface symbol.
3536
int __asan_option_detect_stack_use_after_return; // Global interface symbol.
3637
uptr *__asan_test_only_reported_buggy_pointer; // Used only for testing asan.
3738

@@ -460,7 +461,20 @@ static void AsanInitInternal() {
460461

461462
ReplaceSystemMalloc();
462463

464+
__asan_shadow_memory_dynamic_address = 0;
463465
uptr shadow_start = kLowShadowBeg;
466+
if (shadow_start == 0) {
467+
uptr granularity = GetMmapGranularity();
468+
uptr alignment = 8 * granularity;
469+
uptr left_padding = granularity;
470+
uptr space_size = kHighShadowEnd + left_padding;
471+
472+
shadow_start = FindAvailableMemoryRange(space_size, alignment, granularity);
473+
CHECK_NE((uptr)0, shadow_start);
474+
CHECK(IsAligned(shadow_start, alignment));
475+
}
476+
__asan_shadow_memory_dynamic_address = shadow_start;
477+
464478
if (kLowShadowBeg)
465479
shadow_start -= GetMmapGranularity();
466480
bool full_shadow_is_available =
@@ -472,12 +486,6 @@ static void AsanInitInternal() {
472486
kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;
473487
kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0;
474488
}
475-
#elif SANITIZER_WINDOWS64
476-
// Disable the "mid mem" shadow layout.
477-
if (!full_shadow_is_available) {
478-
kMidMemBeg = 0;
479-
kMidMemEnd = 0;
480-
}
481489
#endif
482490

483491
if (Verbosity()) PrintAddressSpaceLayout();
@@ -650,6 +658,14 @@ void __asan_init() {
650658
AsanInitInternal();
651659
}
652660

661+
// Called by a loaded DLL to initialize itself.
662+
void __asan_init_from_dll(int *detect_stack_use_after_return,
663+
uptr *shadow_memory_dynamic_address) {
664+
__asan_init();
665+
*detect_stack_use_after_return = __asan_option_detect_stack_use_after_return;
666+
*shadow_memory_dynamic_address = __asan_shadow_memory_dynamic_address;
667+
}
668+
653669
void __asan_version_mismatch_check() {
654670
// Do nothing.
655671
}

lib/asan/asan_win_dll_thunk.cc

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -199,23 +199,21 @@ static void InterceptHooks();
199199
// ----------------- ASan own interface functions --------------------
200200
// Don't use the INTERFACE_FUNCTION machinery for this function as we actually
201201
// want to call it in the __asan_init interceptor.
202-
WRAP_W_V(__asan_should_detect_stack_use_after_return)
203-
204202
extern "C" {
205203
int __asan_option_detect_stack_use_after_return;
204+
uptr __asan_shadow_memory_dynamic_address;
206205

207206
// Manually wrap __asan_init as we need to initialize
208207
// __asan_option_detect_stack_use_after_return afterwards.
209208
void __asan_init() {
210-
typedef void (*fntype)();
209+
typedef void (*fntype)(int*, uptr*);
211210
static fntype fn = 0;
212211
// __asan_init is expected to be called by only one thread.
213212
if (fn) return;
214213

215-
fn = (fntype)getRealProcAddressOrDie("__asan_init");
216-
fn();
217-
__asan_option_detect_stack_use_after_return =
218-
(__asan_should_detect_stack_use_after_return() != 0);
214+
fn = (fntype)getRealProcAddressOrDie("__asan_init_from_dll");
215+
fn(&__asan_option_detect_stack_use_after_return,
216+
&__asan_shadow_memory_dynamic_address);
219217

220218
InterceptHooks();
221219
}

lib/asan/asan_win_dynamic_runtime_thunk.cc

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,6 @@
3333
#pragma section(".CRT$XTW", long, read) // NOLINT
3434
#pragma section(".CRT$XTY", long, read) // NOLINT
3535

36-
////////////////////////////////////////////////////////////////////////////////
37-
// Define a copy of __asan_option_detect_stack_use_after_return that should be
38-
// used when linking an MD runtime with a set of object files on Windows.
39-
//
40-
// The ASan MD runtime dllexports '__asan_option_detect_stack_use_after_return',
41-
// so normally we would just dllimport it. Unfortunately, the dllimport
42-
// attribute adds __imp_ prefix to the symbol name of a variable.
43-
// Since in general we don't know if a given TU is going to be used
44-
// with a MT or MD runtime and we don't want to use ugly __imp_ names on Windows
45-
// just to work around this issue, let's clone the variable that is constant
46-
// after initialization anyways.
47-
extern "C" {
48-
__declspec(dllimport) int __asan_should_detect_stack_use_after_return();
49-
int __asan_option_detect_stack_use_after_return =
50-
__asan_should_detect_stack_use_after_return();
51-
}
52-
5336
////////////////////////////////////////////////////////////////////////////////
5437
// For some reason, the MD CRT doesn't call the C/C++ terminators during on DLL
5538
// unload or on exit. ASan relies on LLVM global_dtors to call

lib/sanitizer_common/sanitizer_common.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type);
9898
bool MprotectNoAccess(uptr addr, uptr size);
9999
bool MprotectReadOnly(uptr addr, uptr size);
100100

101+
// Find an available address space.
102+
uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding);
103+
101104
// Used to check if we can map shadow memory to a fixed location.
102105
bool MemoryRangeIsAvailable(uptr range_start, uptr range_end);
103106
void ReleaseMemoryToOS(uptr addr, uptr size);

lib/sanitizer_common/sanitizer_posix.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,11 @@ SignalContext SignalContext::Create(void *siginfo, void *context) {
358358
return SignalContext(context, addr, pc, sp, bp, is_memory_access, write_flag);
359359
}
360360

361+
uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding) {
362+
CHECK("FindAvailableMemoryRange is not available" && 0);
363+
return 0;
364+
}
365+
361366
} // namespace __sanitizer
362367

363368
#endif // SANITIZER_POSIX

lib/sanitizer_common/sanitizer_win.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,26 @@ void DontDumpShadowMemory(uptr addr, uptr length) {
249249
// FIXME: add madvise-analog when we move to 64-bits.
250250
}
251251

252+
uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding) {
253+
uptr address = 0;
254+
while (true) {
255+
MEMORY_BASIC_INFORMATION info;
256+
if (!::VirtualQuery((void*)address, &info, sizeof(info)))
257+
return 0;
258+
259+
if (info.State == MEM_FREE) {
260+
uptr shadow_address = RoundUpTo((uptr)info.BaseAddress + left_padding,
261+
alignment);
262+
if (shadow_address + size < (uptr)info.BaseAddress + info.RegionSize)
263+
return shadow_address;
264+
}
265+
266+
// Move to the next region.
267+
address = (uptr)info.BaseAddress + info.RegionSize;
268+
}
269+
return 0;
270+
}
271+
252272
bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
253273
MEMORY_BASIC_INFORMATION mbi;
254274
CHECK(VirtualQuery((void *)range_start, &mbi, sizeof(mbi)));

0 commit comments

Comments
 (0)