@@ -15,6 +15,7 @@ namespace heap::base {
1515Stack::Stack (const void * stack_start) : stack_start_(stack_start) {}
1616
1717void Stack::SetStackStart (const void * stack_start) {
18+ DCHECK (!context_);
1819 stack_start_ = stack_start;
1920}
2021
@@ -61,29 +62,33 @@ void IterateAsanFakeFrameIfNecessary(StackVisitor* visitor,
6162 // native frame. In case |addr| points to a fake frame of the current stack
6263 // iterate the fake frame. Frame layout see
6364 // https://github.com/google/sanitizers/wiki/AddressSanitizerUseAfterReturn
64- if (asan_fake_stack) {
65- void * fake_frame_begin;
66- void * fake_frame_end;
67- void * real_stack_frame = __asan_addr_is_in_fake_stack (
68- const_cast <void *>(asan_fake_stack), const_cast <void *>(address),
69- &fake_frame_begin, &fake_frame_end);
70- if (real_stack_frame) {
71- // |address| points to a fake frame. Check that the fake frame is part
72- // of this stack.
73- if (stack_start >= real_stack_frame && real_stack_frame >= stack_end) {
74- // Iterate the fake frame.
75- for (const void * const * current =
76- reinterpret_cast <const void * const *>(fake_frame_begin);
77- current < fake_frame_end; ++current) {
78- const void * address = *current;
79- if (address == nullptr ) continue ;
80- visitor->VisitPointer (address);
81- }
65+ if (!asan_fake_stack) return ;
66+ void * fake_frame_begin;
67+ void * fake_frame_end;
68+ void * real_stack_frame = __asan_addr_is_in_fake_stack (
69+ const_cast <void *>(asan_fake_stack), const_cast <void *>(address),
70+ &fake_frame_begin, &fake_frame_end);
71+ if (real_stack_frame) {
72+ // |address| points to a fake frame. Check that the fake frame is part
73+ // of this stack.
74+ if (stack_start >= real_stack_frame && real_stack_frame >= stack_end) {
75+ // Iterate the fake frame.
76+ for (const void * const * current =
77+ reinterpret_cast <const void * const *>(fake_frame_begin);
78+ current < fake_frame_end; ++current) {
79+ const void * address = *current;
80+ if (address == nullptr ) continue ;
81+ visitor->VisitPointer (address);
8282 }
8383 }
8484 }
8585}
86-
86+ #else
87+ void IterateAsanFakeFrameIfNecessary (StackVisitor* visitor,
88+ const void * asan_fake_stack,
89+ const void * stack_start,
90+ const void * stack_end,
91+ const void * address) {}
8792#endif // V8_USE_ADDRESS_SANITIZER
8893
8994void IterateUnsafeStackIfNecessary (StackVisitor* visitor) {
@@ -110,8 +115,6 @@ void IterateUnsafeStackIfNecessary(StackVisitor* visitor) {
110115#endif // defined(__has_feature)
111116}
112117
113- } // namespace
114-
115118// This method should never be inlined to ensure that a possible redzone cannot
116119// contain any data that needs to be scanned.
117120V8_NOINLINE
@@ -121,13 +124,32 @@ DISABLE_ASAN
121124// thread, e.g., for interrupt handling. Atomic reads are not enough as the
122125// other thread may use a lock to synchronize the access.
123126DISABLE_TSAN
127+ void IteratePointersInStack (StackVisitor* visitor, const void * top,
128+ const void * start, const void * asan_fake_stack) {
129+ for (const void * const * current = reinterpret_cast <const void * const *>(top);
130+ current < start; ++current) {
131+ // MSAN: Instead of unpoisoning the whole stack, the slot's value is copied
132+ // into a local which is unpoisoned.
133+ const void * address = *current;
134+ MSAN_MEMORY_IS_INITIALIZED (&address, sizeof (address));
135+ if (address == nullptr ) continue ;
136+ visitor->VisitPointer (address);
137+ IterateAsanFakeFrameIfNecessary (visitor, asan_fake_stack, start, top,
138+ address);
139+ }
140+ }
141+
142+ } // namespace
143+
124144void Stack::IteratePointers (StackVisitor* visitor) const {
125145 DCHECK_NOT_NULL (stack_start_);
126146 DCHECK (context_);
127147 DCHECK_NOT_NULL (context_->stack_marker );
128148
129149#ifdef V8_USE_ADDRESS_SANITIZER
130150 const void * asan_fake_stack = __asan_get_current_fake_stack ();
151+ #else
152+ const void * asan_fake_stack = nullptr ;
131153#endif // V8_USE_ADDRESS_SANITIZER
132154
133155 // Iterate through the registers.
@@ -136,10 +158,8 @@ void Stack::IteratePointers(StackVisitor* visitor) const {
136158 MSAN_MEMORY_IS_INITIALIZED (&address, sizeof (address));
137159 if (address == nullptr ) continue ;
138160 visitor->VisitPointer (address);
139- #ifdef V8_USE_ADDRESS_SANITIZER
140161 IterateAsanFakeFrameIfNecessary (visitor, asan_fake_stack, stack_start_,
141162 context_->stack_marker , address);
142- #endif // V8_USE_ADDRESS_SANITIZER
143163 }
144164
145165 // Iterate through the stack.
@@ -148,19 +168,12 @@ void Stack::IteratePointers(StackVisitor* visitor) const {
148168 constexpr size_t kMinStackAlignment = sizeof (void *);
149169 CHECK_EQ (0u , reinterpret_cast <uintptr_t >(context_->stack_marker ) &
150170 (kMinStackAlignment - 1 ));
151- for (const void * const * current =
152- reinterpret_cast <const void * const *>(context_->stack_marker );
153- current < stack_start_; ++current) {
154- // MSAN: Instead of unpoisoning the whole stack, the slot's value is copied
155- // into a local which is unpoisoned.
156- const void * address = *current;
157- MSAN_MEMORY_IS_INITIALIZED (&address, sizeof (address));
158- if (address == nullptr ) continue ;
159- visitor->VisitPointer (address);
160- #ifdef V8_USE_ADDRESS_SANITIZER
161- IterateAsanFakeFrameIfNecessary (visitor, asan_fake_stack, stack_start_,
162- context_->stack_marker , address);
163- #endif // V8_USE_ADDRESS_SANITIZER
171+ IteratePointersInStack (
172+ visitor, reinterpret_cast <const void * const *>(context_->stack_marker ),
173+ stack_start_, asan_fake_stack);
174+
175+ for (const auto & stack : inactive_stacks_) {
176+ IteratePointersInStack (visitor, stack.top , stack.start , asan_fake_stack);
164177 }
165178
166179 IterateUnsafeStackIfNecessary (visitor);
@@ -219,4 +232,11 @@ void Stack::ClearContext(bool check_invariant) {
219232 context_.reset ();
220233}
221234
235+ void Stack::AddStackSegment (const void * start, const void * top) {
236+ DCHECK_LE (top, start);
237+ inactive_stacks_.push_back ({start, top});
238+ }
239+
240+ void Stack::ClearStackSegments () { inactive_stacks_.clear (); }
241+
222242} // namespace heap::base
0 commit comments