diff options
author | vvvv <vvvv@ydb.tech> | 2024-02-06 20:01:22 +0300 |
---|---|---|
committer | Alexander Smirnov <alex@ydb.tech> | 2024-02-09 19:18:27 +0300 |
commit | ee2b7fbda052aa09b6fdb83b8c6f0305fef3e193 (patch) | |
tree | 102765416c3866bde98a82facc7752d329ee0226 /contrib/libs/llvm16/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp | |
parent | 7494ca32d3a5aca00b7ac527b5f127989335102c (diff) | |
download | ydb-ee2b7fbda052aa09b6fdb83b8c6f0305fef3e193.tar.gz |
llvm16 targets
Diffstat (limited to 'contrib/libs/llvm16/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp')
-rw-r--r-- | contrib/libs/llvm16/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/contrib/libs/llvm16/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp b/contrib/libs/llvm16/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp new file mode 100644 index 0000000000..fdae0e45da --- /dev/null +++ b/contrib/libs/llvm16/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp @@ -0,0 +1,183 @@ +//===--------- RegisterEHFrames.cpp - Register EH frame sections ----------===// +// +// 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/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h" + +#include "llvm/Config/config.h" +#include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/raw_ostream.h" + +#include "llvm/Support/FormatVariadic.h" + +#define DEBUG_TYPE "orc" + +using namespace llvm; +using namespace llvm::orc; +using namespace llvm::orc::shared; + +namespace llvm { +namespace orc { + +#if defined(HAVE_REGISTER_FRAME) && defined(HAVE_DEREGISTER_FRAME) && \ + !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) + +extern "C" void __register_frame(const void *); +extern "C" void __deregister_frame(const void *); + +Error registerFrameWrapper(const void *P) { + __register_frame(P); + return Error::success(); +} + +Error deregisterFrameWrapper(const void *P) { + __deregister_frame(P); + return Error::success(); +} + +#else + +// The building compiler does not have __(de)register_frame but +// it may be found at runtime in a dynamically-loaded library. +// For example, this happens when building LLVM with Visual C++ +// but using the MingW runtime. +static Error registerFrameWrapper(const void *P) { + static void((*RegisterFrame)(const void *)) = 0; + + if (!RegisterFrame) + *(void **)&RegisterFrame = + llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame"); + + if (RegisterFrame) { + RegisterFrame(P); + return Error::success(); + } + + return make_error<StringError>("could not register eh-frame: " + "__register_frame function not found", + inconvertibleErrorCode()); +} + +static Error deregisterFrameWrapper(const void *P) { + static void((*DeregisterFrame)(const void *)) = 0; + + if (!DeregisterFrame) + *(void **)&DeregisterFrame = + llvm::sys::DynamicLibrary::SearchForAddressOfSymbol( + "__deregister_frame"); + + if (DeregisterFrame) { + DeregisterFrame(P); + return Error::success(); + } + + return make_error<StringError>("could not deregister eh-frame: " + "__deregister_frame function not found", + inconvertibleErrorCode()); +} +#endif + +#if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__) + +template <typename HandleFDEFn> +Error walkLibunwindEHFrameSection(const char *const SectionStart, + size_t SectionSize, HandleFDEFn HandleFDE) { + const char *CurCFIRecord = SectionStart; + const char *End = SectionStart + SectionSize; + uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord); + + while (CurCFIRecord != End && Size != 0) { + const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4); + if (Size == 0xffffffff) + Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12; + else + Size += 4; + uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField); + + LLVM_DEBUG({ + dbgs() << "Registering eh-frame section:\n"; + dbgs() << "Processing " << (Offset ? "FDE" : "CIE") << " @" + << (void *)CurCFIRecord << ": ["; + for (unsigned I = 0; I < Size; ++I) + dbgs() << format(" 0x%02" PRIx8, *(CurCFIRecord + I)); + dbgs() << " ]\n"; + }); + + if (Offset != 0) + if (auto Err = HandleFDE(CurCFIRecord)) + return Err; + + CurCFIRecord += Size; + + Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord); + } + + return Error::success(); +} + +#endif // HAVE_UNW_ADD_DYNAMIC_FDE || __APPLE__ + +Error registerEHFrameSection(const void *EHFrameSectionAddr, + size_t EHFrameSectionSize) { + /* libgcc and libunwind __register_frame behave differently. We use the + * presence of __unw_add_dynamic_fde to detect libunwind. */ +#if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__) + // With libunwind, __register_frame has to be called for each FDE entry. + return walkLibunwindEHFrameSection( + static_cast<const char *>(EHFrameSectionAddr), EHFrameSectionSize, + registerFrameWrapper); +#else + // With libgcc, __register_frame takes a single argument: + // a pointer to the start of the .eh_frame section. + + // How can it find the end? Because crtendS.o is linked + // in and it has an .eh_frame section with four zero chars. + return registerFrameWrapper(EHFrameSectionAddr); +#endif +} + +Error deregisterEHFrameSection(const void *EHFrameSectionAddr, + size_t EHFrameSectionSize) { +#if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__) + return walkLibunwindEHFrameSection( + static_cast<const char *>(EHFrameSectionAddr), EHFrameSectionSize, + deregisterFrameWrapper); +#else + return deregisterFrameWrapper(EHFrameSectionAddr); +#endif +} + +} // end namespace orc +} // end namespace llvm + +static Error registerEHFrameWrapper(ExecutorAddrRange EHFrame) { + return llvm::orc::registerEHFrameSection(EHFrame.Start.toPtr<const void *>(), + EHFrame.size()); +} + +static Error deregisterEHFrameWrapper(ExecutorAddrRange EHFrame) { + return llvm::orc::deregisterEHFrameSection( + EHFrame.Start.toPtr<const void *>(), EHFrame.size()); +} + +extern "C" orc::shared::CWrapperFunctionResult +llvm_orc_registerEHFrameSectionWrapper(const char *Data, uint64_t Size) { + return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle( + Data, Size, registerEHFrameWrapper) + .release(); +} + +extern "C" orc::shared::CWrapperFunctionResult +llvm_orc_deregisterEHFrameSectionWrapper(const char *Data, uint64_t Size) { + return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle( + Data, Size, deregisterEHFrameWrapper) + .release(); +} |