Android-x86
Fork
Donation


Commit MetaInfo

Revisiónedb557db300d6632fa6d62f5695cfa9eca6bcbdf (tree)
Tiempo2017-09-05 18:34:19
AutorAndreas Gampe <agampe@goog...>
CommiterChih-Wei Huang

Log Message

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

Cambiar Resumen

Diferencia

--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -545,27 +545,40 @@ void Thread::InstallImplicitProtection() {
545545 //
546546 // We map in the stack by reading every page from the stack bottom (highest address)
547547 // to the stack top. (We then madvise this away.) This must be done by reading from the
548- // current stack pointer downwards. Any access more than a page below the current SP
549- // might cause a segv.
550- // TODO: This comment may be out of date. It seems possible to speed this up. As
551- // this is normally done once in the zygote on startup, ignore for now.
548+ // current stack pointer downwards.
552549 //
553- // AddressSanitizer does not like the part of this functions that reads every stack page.
554- // Looks a lot like an out-of-bounds access.
550+ // Accesses too far below the current machine register corresponding to the stack pointer (e.g.,
551+ // ESP on x86[-32], SP on ARM) might cause a SIGSEGV (at least on x86 with newer kernels). We
552+ // thus have to move the stack pointer. We do this portably by using a recursive function with a
553+ // large stack frame size.
555554
556- // (Defensively) first remove the protection on the protected region as will want to read
555+ // (Defensively) first remove the protection on the protected region as we'll want to read
557556 // and write it. Ignore errors.
558557 UnprotectStack();
559558
560559 VLOG(threads) << "Need to map in stack for thread at " << std::hex <<
561560 static_cast<void*>(pregion);
562561
563- // Read every page from the high address to the low.
564- volatile uint8_t dont_optimize_this;
565- UNUSED(dont_optimize_this);
566- for (uint8_t* p = stack_top; p >= pregion; p -= kPageSize) {
567- dont_optimize_this = *p;
568- }
562+ struct RecurseDownStack {
563+ // This function has an intentionally large stack size.
564+#pragma GCC diagnostic push
565+#pragma GCC diagnostic ignored "-Wframe-larger-than="
566+ NO_INLINE
567+ static void Touch(uintptr_t target) {
568+ volatile size_t zero = 0;
569+ // Use a large local volatile array to ensure a large frame size. Do not use anything close
570+ // to a full page for ASAN. It would be nice to ensure the frame size is at most a page, but
571+ // there is no pragma support for this.
572+ volatile char space[kPageSize - 256];
573+ char sink ATTRIBUTE_UNUSED = space[zero];
574+ if (reinterpret_cast<uintptr_t>(space) >= target + kPageSize) {
575+ Touch(target);
576+ }
577+ zero *= 2; // Try to avoid tail recursion.
578+ }
579+#pragma GCC diagnostic pop
580+ };
581+ RecurseDownStack::Touch(reinterpret_cast<uintptr_t>(pregion));
569582
570583 VLOG(threads) << "(again) installing stack protected region at " << std::hex <<
571584 static_cast<void*>(pregion) << " to " <<
Show on old repository browser