Index: compiler-rt/include/sanitizer/common_interface_defs.h
===================================================================
--- compiler-rt/include/sanitizer/common_interface_defs.h
+++ compiler-rt/include/sanitizer/common_interface_defs.h
@@ -341,6 +341,30 @@
const void **bottom_old,
size_t *size_old);
+/// Calls the user-provided callback for each Fake stack region for the
+/// specified thread ID.
+///
+/// \param os_tid Thread ID. Only the Fake stack of this thread ID is considered.
+/// \param callback User-provided callback. For each stack region,
+/// callback is called with begin and
+/// end marking the stack span and arg
+/// equal to the arg parameter value passed.
+/// \param arg This value is passed as last parameter to callback.
+void __sanitizer_for_each_extra_stack_range(
+ uint64_t os_tid, void (*callback)(size_t begin, size_t end, void *arg),
+ void *arg);
+
+/// Calls the user-provided callback for each Fake stack region for
+/// threads that have a Fake stack.
+///
+/// \param callback User-provided callback. For each stack region,
+/// callback is called with begin and
+/// end marking the stack span and arg
+/// equal to the user-provided arg value.
+/// \param arg This value is passed as last parameter to callback.
+void __sanitizer_for_each_extra_stack_range_all_threads(
+ void (*callback)(size_t begin, size_t end, void *arg), void *arg);
+
// Get full module name and calculate pc offset within it.
// Returns 1 if pc belongs to some module, 0 if module was not found.
int __sanitizer_get_module_and_offset_for_pc(void *pc, char *module_path,
Index: compiler-rt/lib/asan/asan_interface.inc
===================================================================
--- compiler-rt/lib/asan/asan_interface.inc
+++ compiler-rt/lib/asan/asan_interface.inc
@@ -154,6 +154,8 @@
INTERFACE_FUNCTION(__asan_unregister_image_globals)
INTERFACE_FUNCTION(__asan_version_mismatch_check_v8)
INTERFACE_FUNCTION(__sanitizer_finish_switch_fiber)
+INTERFACE_FUNCTION(__sanitizer_for_each_extra_stack_range)
+INTERFACE_FUNCTION(__sanitizer_for_each_extra_stack_range_all_threads)
INTERFACE_FUNCTION(__sanitizer_print_stack_trace)
INTERFACE_FUNCTION(__sanitizer_ptr_cmp)
INTERFACE_FUNCTION(__sanitizer_ptr_sub)
Index: compiler-rt/lib/asan/asan_thread.cpp
===================================================================
--- compiler-rt/lib/asan/asan_thread.cpp
+++ compiler-rt/lib/asan/asan_thread.cpp
@@ -533,4 +533,40 @@
(uptr*)bottom_old,
(uptr*)size_old);
}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_for_each_extra_stack_range(
+ u64 os_id, void (*callback)(uptr begin, uptr end, void *arg), void *arg) {
+ AsanThread *t = GetAsanThreadByOsIDLocked(os_id);
+ if (t && t->has_fake_stack())
+ t->fake_stack()->ForEachFakeFrame(callback, arg);
+}
+
+struct RichRangeIteratorCallback {
+ RangeIteratorCallback callback;
+ void *arg;
+};
+
+static void
+CallRichRangeCallback(ThreadContextBase *tctx_base, void *arg) {
+ auto *cb = reinterpret_cast(arg);
+ auto *tctx = static_cast(tctx_base);
+ AsanThread *t = tctx->thread;
+ if (t && t->has_fake_stack())
+ t->fake_stack()->ForEachFakeFrame(cb->callback, cb->arg);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_for_each_extra_stack_range_all_threads(
+ void (*callback)(uptr begin, uptr end, void *arg), void *arg) {
+ if (!__asan_option_detect_stack_use_after_return)
+ return;
+
+ RichRangeIteratorCallback cb = {callback, arg};
+ {
+ ThreadRegistryLock l(&asanThreadRegistry());
+ asanThreadRegistry().RunCallbackForEachThreadLocked(CallRichRangeCallback,
+ &cb);
+ }
}
+} // extern "C"