This repository has been archived by the owner on Mar 19, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: youling257 <youling257@gmail.com>
- Loading branch information
1 parent
1a57afb
commit ce35454
Showing
1 changed file
with
85 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
From 39e967c05572b2072367ec40304763c0976755f6 Mon Sep 17 00:00:00 2001 | ||
From: Andreas Gampe <agampe@google.com> | ||
Date: Wed, 28 Jun 2017 17:20:15 -0700 | ||
Subject: [PATCH] ART: Change main-thread thread paging scheme | ||
|
||
Modify the code that ensures we can install a stack guard page into | ||
the main thread. | ||
|
||
A recent kernel change means that our previous approach of using a | ||
free pointer does not work. It is important to actually extend the | ||
stack properly. For portability, use a function with a large stack | ||
frame (suggested by and adapted from hboehm). | ||
|
||
Bug: 62952017 | ||
Test: m | ||
Test: m test-art-host | ||
Test: Device boots (x86_64 emulator) | ||
Test: Device boots (bullhead) | ||
Change-Id: Ic2a0c3d6d05a1ea9f655329d147b46949e1b9db3 | ||
Signed-off-by: youling257 <youling257@gmail.com> | ||
--- | ||
runtime/thread.cc | 39 ++++++++++++++++++++++++++------------- | ||
1 file changed, 26 insertions(+), 13 deletions(-) | ||
|
||
diff --git a/runtime/thread.cc b/runtime/thread.cc | ||
index f3b39c9d1..f6b89bc53 100644 | ||
--- a/runtime/thread.cc | ||
+++ b/runtime/thread.cc | ||
@@ -546,27 +546,40 @@ void Thread::InstallImplicitProtection() { | ||
// | ||
// We map in the stack by reading every page from the stack bottom (highest address) | ||
// to the stack top. (We then madvise this away.) This must be done by reading from the | ||
- // current stack pointer downwards. Any access more than a page below the current SP | ||
- // might cause a segv. | ||
- // TODO: This comment may be out of date. It seems possible to speed this up. As | ||
- // this is normally done once in the zygote on startup, ignore for now. | ||
+ // current stack pointer downwards. | ||
// | ||
- // AddressSanitizer does not like the part of this functions that reads every stack page. | ||
- // Looks a lot like an out-of-bounds access. | ||
+ // Accesses too far below the current machine register corresponding to the stack pointer (e.g., | ||
+ // ESP on x86[-32], SP on ARM) might cause a SIGSEGV (at least on x86 with newer kernels). We | ||
+ // thus have to move the stack pointer. We do this portably by using a recursive function with a | ||
+ // large stack frame size. | ||
|
||
- // (Defensively) first remove the protection on the protected region as will want to read | ||
+ // (Defensively) first remove the protection on the protected region as we'll want to read | ||
// and write it. Ignore errors. | ||
UnprotectStack(); | ||
|
||
VLOG(threads) << "Need to map in stack for thread at " << std::hex << | ||
static_cast<void*>(pregion); | ||
|
||
- // Read every page from the high address to the low. | ||
- volatile uint8_t dont_optimize_this; | ||
- UNUSED(dont_optimize_this); | ||
- for (uint8_t* p = stack_top; p >= pregion; p -= kPageSize) { | ||
- dont_optimize_this = *p; | ||
- } | ||
+ struct RecurseDownStack { | ||
+ // This function has an intentionally large stack size. | ||
+#pragma GCC diagnostic push | ||
+#pragma GCC diagnostic ignored "-Wframe-larger-than=" | ||
+ NO_INLINE | ||
+ static void Touch(uintptr_t target) { | ||
+ volatile size_t zero = 0; | ||
+ // Use a large local volatile array to ensure a large frame size. Do not use anything close | ||
+ // to a full page for ASAN. It would be nice to ensure the frame size is at most a page, but | ||
+ // there is no pragma support for this. | ||
+ volatile char space[kPageSize - 256]; | ||
+ char sink ATTRIBUTE_UNUSED = space[zero]; | ||
+ if (reinterpret_cast<uintptr_t>(space) >= target + kPageSize) { | ||
+ Touch(target); | ||
+ } | ||
+ zero *= 2; // Try to avoid tail recursion. | ||
+ } | ||
+#pragma GCC diagnostic pop | ||
+ }; | ||
+ RecurseDownStack::Touch(reinterpret_cast<uintptr_t>(pregion)); | ||
|
||
VLOG(threads) << "(again) installing stack protected region at " << std::hex << | ||
static_cast<void*>(pregion) << " to " << | ||
-- | ||
2.17.0 | ||
|