[vm] Add missing save of shadow call stack in DartEntryScope.

Thread::saved_shadow_call_stack_ has the value for the top-most Dart entry, and needs to be saved and restored for nested Dart entries.

TEST=fuchsia
Change-Id: Id035bec7e798458fdfcf85678a7246d5f7eef850
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/464603
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
This commit is contained in:
Ryan Macnak
2025-11-26 10:44:51 -08:00
committed by Commit Queue
parent a27682c68e
commit 2a446270a4
4 changed files with 42 additions and 15 deletions
+13 -4
View File
@@ -52,8 +52,11 @@ class DartEntryScope : public TransitionToGenerated {
#if defined(USING_SAFE_STACK)
// Remember the safestack pointer at entry so it can be restored in
// Exceptions::JumpToFrame when a Dart exception jumps over C++ frames.
saved_safestack_limit_ = OSThread::GetCurrentSafestackPointer();
thread->set_saved_safestack_limit(saved_safestack_limit_);
saved_safestack_ = thread->saved_safestack();
thread->set_saved_safestack(OSThread::GetCurrentSafestackPointer());
#endif
#if defined(USING_SHADOW_CALL_STACK)
saved_shadow_call_stack_ = thread->saved_shadow_call_stack();
#endif
saved_api_scope_ = thread->api_top_scope();
@@ -67,8 +70,11 @@ class DartEntryScope : public TransitionToGenerated {
thread()->ExitApiScope();
}
#if defined(USING_SHADOW_CALL_STACK)
thread()->set_saved_shadow_call_stack(saved_shadow_call_stack_);
#endif
#if defined(USING_SAFE_STACK)
thread()->set_saved_safestack_limit(saved_safestack_limit_);
thread()->set_saved_safestack(saved_safestack_);
#endif
ASSERT(thread()->long_jump_base() == nullptr);
@@ -78,7 +84,10 @@ class DartEntryScope : public TransitionToGenerated {
private:
LongJumpScope* saved_long_jump_base_;
#if defined(USING_SAFE_STACK)
uword saved_safestack_limit_ = 0;
uword saved_safestack_ = 0;
#endif
#if defined(USING_SHADOW_CALL_STACK)
uword saved_shadow_call_stack_ = 0;
#endif
ApiLocalScope* saved_api_scope_;
};
+1 -1
View File
@@ -650,7 +650,7 @@ NO_SANITIZE_SAFE_STACK // This function manipulates the safestack pointer.
// We are jumping over C++ frames, so we have to set the safestack pointer
// back to what it was when we entered the runtime from Dart code.
#if defined(USING_SAFE_STACK)
const uword saved_ssp = thread->saved_safestack_limit();
const uword saved_ssp = thread->saved_safestack();
OSThread::SetCurrentSafestackPointer(saved_ssp);
#endif
+11 -1
View File
@@ -153,7 +153,7 @@ void OSThread::Join(ThreadJoinId id) {
}
void OSThread::Detach(ThreadJoinId id) {
int result = pthread_detach(id);
int result = pthread_detach(id); // NOLINT
VALIDATE_PTHREAD_RESULT(result);
}
@@ -202,6 +202,10 @@ uword OSThread::GetCurrentSafestackPointer() {
asm volatile("mrs %0, TPIDR_EL0;\n" _loadword(ZX_TLS_UNSAFE_SP_OFFSET)
: "=r"(result) // outputs
);
#elif defined(HOST_ARCH_RISCV64)
asm volatile("ld %0, " STRINGIFY(ZX_TLS_UNSAFE_SP_OFFSET) "(tp)"
: "=r"(result) // outputs
);
#else
#error "Architecture not supported"
#endif
@@ -229,6 +233,12 @@ void OSThread::SetCurrentSafestackPointer(uword ssp) {
: "r"(ssp) // inputs.
: // clobbered.
);
#elif defined(HOST_ARCH_RISCV64)
asm volatile("sd %0, " STRINGIFY(ZX_TLS_UNSAFE_SP_OFFSET) "(tp)"
: // outputs.
: "r"(ssp) // inputs.
: // clobbered.
);
#else
#error "Architecture not supported"
#endif
+17 -9
View File
@@ -425,9 +425,9 @@ class Thread : public ThreadState, public IntrusiveDListEntry<Thread> {
void SetStackLimit(uword value);
void ClearStackLimit();
// Access to the current stack limit for generated code. Either the true OS
// thread's stack limit minus some headroom, or a special value to trigger
// interrupts.
// The stack limit used by stack overflow checks in generated code. Either the
// true OS thread's stack limit minus some headroom, or a special value to
// trigger interrupts.
uword stack_limit_address() const {
return reinterpret_cast<uword>(&stack_limit_);
}
@@ -435,19 +435,27 @@ class Thread : public ThreadState, public IntrusiveDListEntry<Thread> {
return OFFSET_OF(Thread, stack_limit_);
}
// The true stack limit for this OS thread.
// The true stack limit for this OS thread minus some headroom. Used on ARM64
// to keep CSP/R31 signal-handler safe while Dart uses R15 as its stack
// pointer.
static intptr_t saved_stack_limit_offset() {
return OFFSET_OF(Thread, saved_stack_limit_);
}
uword saved_stack_limit() const { return saved_stack_limit_; }
#if defined(USING_SAFE_STACK)
uword saved_safestack_limit() const { return saved_safestack_limit_; }
void set_saved_safestack_limit(uword limit) {
saved_safestack_limit_ = limit;
}
// The SafeStack pointer during the top-most DartEntry. Needs to be restored
// on Dart throw like longjmp would.
uword saved_safestack() const { return saved_safestack_; }
void set_saved_safestack(uword ssp) { saved_safestack_ = ssp; }
#endif
// The ShadowCallStack pointer during the top-most entry frame. Needs to be
// restored on Dart throw like longjmp would.
uword saved_shadow_call_stack() const { return saved_shadow_call_stack_; }
void set_saved_shadow_call_stack(uword ssp) {
saved_shadow_call_stack_ = ssp;
}
static uword saved_shadow_call_stack_offset() {
return OFFSET_OF(Thread, saved_shadow_call_stack_);
}
@@ -1634,7 +1642,7 @@ class Thread : public ThreadState, public IntrusiveDListEntry<Thread> {
}
#if defined(USING_SAFE_STACK)
uword saved_safestack_limit_ = 0;
uword saved_safestack_ = 0;
#endif
Thread* next_; // Used to chain the thread structures in an isolate.