================ @@ -0,0 +1,115 @@ +//===--- RunOnNewStack.cpp - Crash Recovery -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ProgramStack.h" +#include "llvm/Config/config.h" +#include "llvm/Support/Compiler.h" + +#ifdef HAVE_SYS_RESOURCE_H +# include <sys/resource.h> +#endif + +#ifdef _MSC_VER +# include <intrin.h> // for _AddressOfReturnAddress +#endif + +// Currently only Apple AArch64 is known to support split stacks in the debugger +// and other tooling. +#if defined(__APPLE__) && defined(__aarch64__) && \ + LLVM_HAS_CPP_ATTRIBUTE(gnu::naked) && __has_extension(gnu_asm) +# define LLVM_HAS_SPLIT_STACKS +# define LLVM_HAS_SPLIT_STACKS_AARCH64 +#include <sys/mman.h> +#endif + +#ifndef LLVM_HAS_SPLIT_STACKS +# include "llvm/Support/thread.h" +#endif + +using namespace llvm; + +uintptr_t llvm::getStackPointer() { +#if __GNUC__ || __has_builtin(__builtin_frame_address) + return (uintptr_t)__builtin_frame_address(0); +#elif defined(_MSC_VER) + return (uintptr_t)_AddressOfReturnAddress(); +#else + char CharOnStack = 0; + // The volatile store here is intended to escape the local variable, to + // prevent the compiler from optimizing CharOnStack into anything other + // than a char on the stack. + // + // Tested on: MSVC 2015 - 2019, GCC 4.9 - 9, Clang 3.2 - 9, ICC 13 - 19. + char *volatile Ptr = &CharOnStack; + return (uintptr_t)Ptr; +#endif +} + +unsigned llvm::getDefaultStackSize() { +#ifdef HAVE_SYS_RESOURCE_H + rlimit RL; + getrlimit(RLIMIT_STACK, &RL); + return RL.rlim_cur; +#else + // 8MiB seems good. + return 8 << 20; +#endif +} + +namespace { +#ifdef LLVM_HAS_SPLIT_STACKS_AARCH64 +[[gnu::naked]] void runOnNewStackImpl(void *Stack, void (*Fn)(void *), + void *Ctx) { + __asm__ volatile( + "mov x16, sp\n\t" + "sub x0, x0, #0x20\n\t" // subtract space from stack + "stp xzr, x16, [x0, #0x00]\n\t" // save old sp + "stp x29, x30, [x0, #0x10]\n\t" // save fp, lr + "mov sp, x0\n\t" // switch to new stack + "add x29, x0, #0x10\n\t" // switch to new frame + ".cfi_def_cfa w29, 16\n\t" + ".cfi_offset w30, -8\n\t" // lr + ".cfi_offset w29, -16\n\t" // fp + + "mov x0, x2\n\t" // Ctx is the only argument + "blr x1\n\t" // call Fn + + "ldp x29, x30, [sp, #0x10]\n\t" // restore fp, lr + "ldp xzr, x16, [sp, #0x00]\n\t" // load old sp + "mov sp, x16\n\t" + "ret" + ); +} +#endif + +#ifdef LLVM_HAS_SPLIT_STACKS +void callback(void *Ctx) { + (*reinterpret_cast<function_ref<void()> *>(Ctx))(); +} +#endif +} // namespace + +#ifdef LLVM_HAS_SPLIT_STACKS +void llvm::runOnNewStack(unsigned StackSize, function_ref<void()> Fn) { + if (StackSize == 0) + StackSize = getDefaultStackSize(); + + void *Stack = malloc(StackSize); ---------------- rnk wrote:
I was going to suggest it, but I guess it's not worth it. For an 8MB allocation, a reasonable allocator will probably call mmap, and if we end up crossing this stack size boundary in a loop, malloc has the internal caching optimizations to avoid repeated mmap syscalls. Actually, that's a good reason to *prefer* malloc, you should add a comment to that effect. https://github.com/llvm/llvm-project/pull/133173 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits