chromium/base/allocator/partition_allocator/src/partition_alloc/stack/stack.cc

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "partition_alloc/stack/stack.h"

#include <cstdint>
#include <limits>

#include "partition_alloc/build_config.h"
#include "partition_alloc/buildflags.h"
#include "partition_alloc/partition_alloc_base/compiler_specific.h"
#include "partition_alloc/partition_alloc_check.h"

#if PA_BUILDFLAG(IS_WIN)
#include <windows.h>
#else
#include <pthread.h>
#endif

#if PA_BUILDFLAG(PA_LIBC_GLIBC)
extern "C" void* __libc_stack_end;
#endif

namespace partition_alloc::internal {

#if PA_BUILDFLAG(IS_WIN)

void* GetStackTop() {
#if PA_BUILDFLAG(PA_ARCH_CPU_X86_64)
  return reinterpret_cast<void*>(
      reinterpret_cast<NT_TIB64*>(NtCurrentTeb())->StackBase);
#elif PA_BUILDFLAG(PA_ARCH_CPU_32_BITS)
  return reinterpret_cast<void*>(
      reinterpret_cast<NT_TIB*>(NtCurrentTeb())->StackBase);
#elif PA_BUILDFLAG(PA_ARCH_CPU_ARM64)
  // Windows 8 and later, see
  // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentthreadstacklimits
  ULONG_PTR lowLimit, highLimit;
  ::GetCurrentThreadStackLimits(&lowLimit, &highLimit);
  return reinterpret_cast<void*>(highLimit);
#else
#error "Unsupported GetStackStart"
#endif
}

#elif PA_BUILDFLAG(IS_APPLE)

void* GetStackTop() {
  return pthread_get_stackaddr_np(pthread_self());
}

#elif PA_BUILDFLAG(IS_POSIX) || PA_BUILDFLAG(IS_FUCHSIA)

void* GetStackTop() {}

#else  // PA_BUILDFLAG(IS_WIN)
#error "Unsupported GetStackTop"
#endif  // PA_BUILDFLAG(IS_WIN)

IterateStackCallback;
extern "C" void PAPushAllRegistersAndIterateStack(const Stack*,
                                                  StackVisitor*,
                                                  IterateStackCallback);

Stack::Stack(void* stack_top) :{}

PA_NOINLINE uintptr_t* GetStackPointer() {}

namespace {

[[maybe_unused]] void IterateSafeStackIfNecessary(StackVisitor* visitor) {}

// Called by the trampoline that pushes registers on the stack. This method
// should never be inlined to ensure that a possible redzone cannot contain
// any data that needs to be scanned.
// No ASAN support as method accesses redzones while walking the stack.
[[maybe_unused]] PA_NOINLINE PA_NO_SANITIZE("address") void IteratePointersImpl(
    const Stack* stack,
    StackVisitor* visitor,
    uintptr_t* stack_ptr) {}

}  // namespace

void Stack::IteratePointers(StackVisitor* visitor) const {}

StackTopRegistry::StackTopRegistry() = default;
StackTopRegistry::~StackTopRegistry() = default;

// static
StackTopRegistry& StackTopRegistry::Get() {}

void StackTopRegistry::NotifyThreadCreated(void* stack_top) {}

void StackTopRegistry::NotifyThreadDestroyed() {}

void* StackTopRegistry::GetCurrentThreadStackTop() const {}

}  // namespace partition_alloc::internal