Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp
96380 views
//===--------- RegisterEHFrames.cpp - Register EH frame sections ----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"910#include "llvm/Config/config.h"11#include "llvm/ExecutionEngine/JITSymbol.h"12#include "llvm/Support/BinaryStreamReader.h"13#include "llvm/Support/Compiler.h"14#include "llvm/Support/Debug.h"15#include "llvm/Support/DynamicLibrary.h"16#include "llvm/Support/raw_ostream.h"1718#include "llvm/Support/FormatVariadic.h"1920#define DEBUG_TYPE "orc"2122using namespace llvm;23using namespace llvm::orc;24using namespace llvm::orc::shared;2526namespace llvm {27namespace orc {2829#if defined(HAVE_REGISTER_FRAME) && defined(HAVE_DEREGISTER_FRAME) && \30!defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)3132extern "C" void __register_frame(const void *);33extern "C" void __deregister_frame(const void *);3435Error registerFrameWrapper(const void *P) {36__register_frame(P);37return Error::success();38}3940Error deregisterFrameWrapper(const void *P) {41__deregister_frame(P);42return Error::success();43}4445#else4647// The building compiler does not have __(de)register_frame but48// it may be found at runtime in a dynamically-loaded library.49// For example, this happens when building LLVM with Visual C++50// but using the MingW runtime.51static Error registerFrameWrapper(const void *P) {52static void((*RegisterFrame)(const void *)) = 0;5354if (!RegisterFrame)55*(void **)&RegisterFrame =56llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");5758if (RegisterFrame) {59RegisterFrame(P);60return Error::success();61}6263return make_error<StringError>("could not register eh-frame: "64"__register_frame function not found",65inconvertibleErrorCode());66}6768static Error deregisterFrameWrapper(const void *P) {69static void((*DeregisterFrame)(const void *)) = 0;7071if (!DeregisterFrame)72*(void **)&DeregisterFrame =73llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(74"__deregister_frame");7576if (DeregisterFrame) {77DeregisterFrame(P);78return Error::success();79}8081return make_error<StringError>("could not deregister eh-frame: "82"__deregister_frame function not found",83inconvertibleErrorCode());84}85#endif8687#if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__)8889template <typename HandleFDEFn>90Error walkLibunwindEHFrameSection(const char *const SectionStart,91size_t SectionSize, HandleFDEFn HandleFDE) {92const char *CurCFIRecord = SectionStart;93const char *End = SectionStart + SectionSize;94uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);9596while (CurCFIRecord != End && Size != 0) {97const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);98if (Size == 0xffffffff)99Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;100else101Size += 4;102uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);103104LLVM_DEBUG({105dbgs() << "Registering eh-frame section:\n";106dbgs() << "Processing " << (Offset ? "FDE" : "CIE") << " @"107<< (void *)CurCFIRecord << ": [";108for (unsigned I = 0; I < Size; ++I)109dbgs() << format(" 0x%02" PRIx8, *(CurCFIRecord + I));110dbgs() << " ]\n";111});112113if (Offset != 0)114if (auto Err = HandleFDE(CurCFIRecord))115return Err;116117CurCFIRecord += Size;118119Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);120}121122return Error::success();123}124125#endif // HAVE_UNW_ADD_DYNAMIC_FDE || __APPLE__126127Error registerEHFrameSection(const void *EHFrameSectionAddr,128size_t EHFrameSectionSize) {129/* libgcc and libunwind __register_frame behave differently. We use the130* presence of __unw_add_dynamic_fde to detect libunwind. */131#if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__)132// With libunwind, __register_frame has to be called for each FDE entry.133return walkLibunwindEHFrameSection(134static_cast<const char *>(EHFrameSectionAddr), EHFrameSectionSize,135registerFrameWrapper);136#else137// With libgcc, __register_frame takes a single argument:138// a pointer to the start of the .eh_frame section.139140// How can it find the end? Because crtendS.o is linked141// in and it has an .eh_frame section with four zero chars.142return registerFrameWrapper(EHFrameSectionAddr);143#endif144}145146Error deregisterEHFrameSection(const void *EHFrameSectionAddr,147size_t EHFrameSectionSize) {148#if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__)149return walkLibunwindEHFrameSection(150static_cast<const char *>(EHFrameSectionAddr), EHFrameSectionSize,151deregisterFrameWrapper);152#else153return deregisterFrameWrapper(EHFrameSectionAddr);154#endif155}156157} // end namespace orc158} // end namespace llvm159160static Error registerEHFrameWrapper(ExecutorAddrRange EHFrame) {161return llvm::orc::registerEHFrameSection(EHFrame.Start.toPtr<const void *>(),162EHFrame.size());163}164165static Error deregisterEHFrameWrapper(ExecutorAddrRange EHFrame) {166return llvm::orc::deregisterEHFrameSection(167EHFrame.Start.toPtr<const void *>(), EHFrame.size());168}169170extern "C" orc::shared::CWrapperFunctionResult171llvm_orc_registerEHFrameSectionWrapper(const char *Data, uint64_t Size) {172return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(173Data, Size, registerEHFrameWrapper)174.release();175}176177extern "C" orc::shared::CWrapperFunctionResult178llvm_orc_deregisterEHFrameSectionWrapper(const char *Data, uint64_t Size) {179return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(180Data, Size, deregisterEHFrameWrapper)181.release();182}183184185