base: Add Stack utilities
Adds: - GetStackStart - GetCurrentStackPosition - GetStackSlot which translates a stack slot through ASAN if needed Bug: v8:10354, chromium:1056170 Change-Id: I28e76f41de28415382f7cc32729e86d71e9f8f19 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2122033 Commit-Queue: Michael Lippautz <mlippautz@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Cr-Commit-Position: refs/heads/master@{#66890}
This commit is contained in:
parent
0f4d68dac9
commit
da4099299f
@ -96,5 +96,23 @@ void OS::SignalCodeMovingGC() {}
|
||||
|
||||
void OS::AdjustSchedulingParams() {}
|
||||
|
||||
// static
|
||||
void* Stack::GetStackStart() {
|
||||
pthread_attr_t attr;
|
||||
int error;
|
||||
pthread_attr_init(&attr);
|
||||
error = pthread_attr_get_np(pthread_self(), &attr);
|
||||
if (!error) {
|
||||
void* base;
|
||||
size_t size;
|
||||
error = pthread_attr_getstack(&attr, &base, &size);
|
||||
CHECK(!error);
|
||||
pthread_attr_destroy(&attr);
|
||||
return reinterpret_cast<uint8_t*>(base) + size;
|
||||
}
|
||||
pthread_attr_destroy(&attr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
} // namespace v8
|
||||
|
@ -93,5 +93,10 @@ void OS::AdjustSchedulingParams() {
|
||||
#endif
|
||||
}
|
||||
|
||||
// static
|
||||
void* Stack::GetStackStart() {
|
||||
return pthread_get_stackaddr_np(pthread_self());
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
} // namespace v8
|
||||
|
@ -81,6 +81,10 @@ extern int madvise(caddr_t, size_t, int);
|
||||
#define MADV_FREE MADV_DONTNEED
|
||||
#endif
|
||||
|
||||
#if defined(V8_LIBC_GLIBC)
|
||||
extern "C" void* __libc_stack_end; // NOLINT
|
||||
#endif
|
||||
|
||||
namespace v8 {
|
||||
namespace base {
|
||||
|
||||
@ -963,6 +967,40 @@ void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
|
||||
USE(result);
|
||||
}
|
||||
|
||||
// pthread_getattr_np used below is non portable (hence the _np suffix). We
|
||||
// keep this version in POSIX as most Linux-compatible derivatives will
|
||||
// support it. MacOS and FreeBSD are different here.
|
||||
#if !defined(V8_OS_FREEBSD) && !defined(V8_OS_MACOSX)
|
||||
|
||||
// static
|
||||
void* Stack::GetStackStart() {
|
||||
pthread_attr_t attr;
|
||||
int error = pthread_getattr_np(pthread_self(), &attr);
|
||||
if (!error) {
|
||||
void* base;
|
||||
size_t size;
|
||||
error = pthread_attr_getstack(&attr, &base, &size);
|
||||
CHECK(!error);
|
||||
pthread_attr_destroy(&attr);
|
||||
return reinterpret_cast<uint8_t*>(base) + size;
|
||||
}
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
#if defined(V8_LIBC_GLIBC)
|
||||
// pthread_getattr_np can fail for the main thread. In this case
|
||||
// just like NaCl we rely on the __libc_stack_end to give us
|
||||
// the start of the stack.
|
||||
// See https://code.google.com/p/nativeclient/issues/detail?id=3431.
|
||||
return __libc_stack_end;
|
||||
#endif // !defined(V8_LIBC_GLIBC)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif // !defined(V8_OS_FREEBSD) && !defined(V8_OS_MACOSX)
|
||||
|
||||
// static
|
||||
void* Stack::GetCurrentStackPosition() { return __builtin_frame_address(0); }
|
||||
|
||||
#undef LOG_TAG
|
||||
#undef MAP_ANONYMOUS
|
||||
#undef MADV_FREE
|
||||
|
@ -1394,5 +1394,23 @@ void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
|
||||
|
||||
void OS::AdjustSchedulingParams() {}
|
||||
|
||||
// static
|
||||
void* Stack::GetStackStart() {
|
||||
#if defined(V8_TARGET_ARCH_32_BIT)
|
||||
return reinterpret_cast<void*>(__readfsdword(offsetof(NT_TIB, StackBase)));
|
||||
#else
|
||||
return reinterpret_cast<void*>(__readgsqword(offsetof(NT_TIB64, StackBase)));
|
||||
#endif
|
||||
}
|
||||
|
||||
// static
|
||||
void* Stack::GetCurrentStackPosition() {
|
||||
#if V8_CC_MSVC
|
||||
return _AddressOfReturnAddress();
|
||||
#else
|
||||
return __builtin_frame_address(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
} // namespace v8
|
||||
|
@ -35,6 +35,10 @@
|
||||
#include "src/base/qnx-math.h"
|
||||
#endif
|
||||
|
||||
#ifdef V8_USE_ADDRESS_SANITIZER
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#endif // V8_USE_ADDRESS_SANITIZER
|
||||
|
||||
namespace v8 {
|
||||
|
||||
namespace base {
|
||||
@ -407,6 +411,38 @@ class V8_BASE_EXPORT Thread {
|
||||
DISALLOW_COPY_AND_ASSIGN(Thread);
|
||||
};
|
||||
|
||||
// TODO(v8:10354): Make use of the stack utilities here in V8.
|
||||
class V8_BASE_EXPORT Stack {
|
||||
public:
|
||||
// Gets the start of the stack of the current thread.
|
||||
static void* GetStackStart();
|
||||
|
||||
// Returns the current stack top. Works correctly with ASAN and SafeStack.
|
||||
// GetCurrentStackPosition() should not be inlined, because it works on stack
|
||||
// frames if it were inlined into a function with a huge stack frame it would
|
||||
// return an address significantly above the actual current stack position.
|
||||
static V8_NOINLINE void* GetCurrentStackPosition();
|
||||
|
||||
// Translates an ASAN-based slot to a real stack slot if necessary.
|
||||
static void* GetStackSlot(void* slot) {
|
||||
#ifdef V8_USE_ADDRESS_SANITIZER
|
||||
void* fake_stack = __asan_get_current_fake_stack();
|
||||
if (fake_stack) {
|
||||
void* fake_frame_start;
|
||||
void* real_frame = __asan_addr_is_in_fake_stack(
|
||||
fake_stack, slot, &fake_frame_start, nullptr);
|
||||
if (real_frame) {
|
||||
return reinterpret_cast<void*>(
|
||||
reinterpret_cast<uintptr_t>(real_frame) +
|
||||
(reinterpret_cast<uintptr_t>(slot) -
|
||||
reinterpret_cast<uintptr_t>(fake_frame_start)));
|
||||
}
|
||||
}
|
||||
#endif // V8_USE_ADDRESS_SANITIZER
|
||||
return slot;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
} // namespace v8
|
||||
|
||||
|
@ -83,5 +83,18 @@ TEST_F(ThreadLocalStorageTest, DoTest) {
|
||||
Join();
|
||||
}
|
||||
|
||||
TEST(StackTest, GetStackStart) { EXPECT_NE(nullptr, Stack::GetStackStart()); }
|
||||
|
||||
TEST(StackTest, GetCurrentStackPosition) {
|
||||
EXPECT_NE(nullptr, Stack::GetCurrentStackPosition());
|
||||
}
|
||||
|
||||
TEST(StackTest, StackVariableInBounds) {
|
||||
void* dummy;
|
||||
ASSERT_GT(Stack::GetStackStart(), Stack::GetCurrentStackPosition());
|
||||
EXPECT_GT(Stack::GetStackStart(), Stack::GetStackSlot(&dummy));
|
||||
EXPECT_LT(Stack::GetCurrentStackPosition(), Stack::GetStackSlot(&dummy));
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
} // namespace v8
|
||||
|
Loading…
Reference in New Issue
Block a user