brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.9 KiB · f44a5f2 Raw
181 lines · cpp
1//===--------- RegisterEHFrames.cpp - Register EH frame sections ----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"10 11#include "llvm/Config/config.h"12#include "llvm/Support/Compiler.h"13#include "llvm/Support/DynamicLibrary.h"14#include "llvm/Support/raw_ostream.h"15 16#define DEBUG_TYPE "orc"17 18using namespace llvm;19using namespace llvm::orc;20using namespace llvm::orc::shared;21 22namespace llvm {23namespace orc {24 25#if defined(HAVE_REGISTER_FRAME) && defined(HAVE_DEREGISTER_FRAME) &&          \26    !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)27 28extern "C" void __register_frame(const void *);29extern "C" void __deregister_frame(const void *);30 31Error registerFrameWrapper(const void *P) {32  __register_frame(P);33  return Error::success();34}35 36Error deregisterFrameWrapper(const void *P) {37  __deregister_frame(P);38  return Error::success();39}40 41#else42 43// The building compiler does not have __(de)register_frame but44// it may be found at runtime in a dynamically-loaded library.45// For example, this happens when building LLVM with Visual C++46// but using the MingW runtime.47static Error registerFrameWrapper(const void *P) {48  static void((*RegisterFrame)(const void *)) = 0;49 50  if (!RegisterFrame)51    *(void **)&RegisterFrame =52        llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");53 54  if (RegisterFrame) {55    RegisterFrame(P);56    return Error::success();57  }58 59  return make_error<StringError>("could not register eh-frame: "60                                 "__register_frame function not found",61                                 inconvertibleErrorCode());62}63 64static Error deregisterFrameWrapper(const void *P) {65  static void((*DeregisterFrame)(const void *)) = 0;66 67  if (!DeregisterFrame)68    *(void **)&DeregisterFrame =69        llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(70            "__deregister_frame");71 72  if (DeregisterFrame) {73    DeregisterFrame(P);74    return Error::success();75  }76 77  return make_error<StringError>("could not deregister eh-frame: "78                                 "__deregister_frame function not found",79                                 inconvertibleErrorCode());80}81#endif82 83#if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__)84 85template <typename HandleFDEFn>86Error walkLibunwindEHFrameSection(const char *const SectionStart,87                                  size_t SectionSize, HandleFDEFn HandleFDE) {88  const char *CurCFIRecord = SectionStart;89  const char *End = SectionStart + SectionSize;90  uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);91 92  while (CurCFIRecord != End && Size != 0) {93    const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);94    if (Size == 0xffffffff)95      Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;96    else97      Size += 4;98    uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);99 100    LLVM_DEBUG({101      dbgs() << "Registering eh-frame section:\n";102      dbgs() << "Processing " << (Offset ? "FDE" : "CIE") << " @"103             << (void *)CurCFIRecord << ": [";104      for (unsigned I = 0; I < Size; ++I)105        dbgs() << format(" 0x%02" PRIx8, *(CurCFIRecord + I));106      dbgs() << " ]\n";107    });108 109    if (Offset != 0)110      if (auto Err = HandleFDE(CurCFIRecord))111        return Err;112 113    CurCFIRecord += Size;114 115    Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);116  }117 118  return Error::success();119}120 121#endif // HAVE_UNW_ADD_DYNAMIC_FDE || __APPLE__122 123Error registerEHFrameSection(const void *EHFrameSectionAddr,124                             size_t EHFrameSectionSize) {125  /* libgcc and libunwind __register_frame behave differently. We use the126   * presence of __unw_add_dynamic_fde to detect libunwind. */127#if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__)128  // With libunwind, __register_frame has to be called for each FDE entry.129  return walkLibunwindEHFrameSection(130      static_cast<const char *>(EHFrameSectionAddr), EHFrameSectionSize,131      registerFrameWrapper);132#else133  // With libgcc, __register_frame takes a single argument:134  // a pointer to the start of the .eh_frame section.135 136  // How can it find the end? Because crtendS.o is linked137  // in and it has an .eh_frame section with four zero chars.138  return registerFrameWrapper(EHFrameSectionAddr);139#endif140}141 142Error deregisterEHFrameSection(const void *EHFrameSectionAddr,143                               size_t EHFrameSectionSize) {144#if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__)145  return walkLibunwindEHFrameSection(146      static_cast<const char *>(EHFrameSectionAddr), EHFrameSectionSize,147      deregisterFrameWrapper);148#else149  return deregisterFrameWrapper(EHFrameSectionAddr);150#endif151}152 153} // end namespace orc154} // end namespace llvm155 156static Error registerEHFrameWrapper(ExecutorAddrRange EHFrame) {157  return llvm::orc::registerEHFrameSection(EHFrame.Start.toPtr<const void *>(),158                                           EHFrame.size());159}160 161static Error deregisterEHFrameWrapper(ExecutorAddrRange EHFrame) {162  return llvm::orc::deregisterEHFrameSection(163      EHFrame.Start.toPtr<const void *>(), EHFrame.size());164}165 166extern "C" orc::shared::CWrapperFunctionResult167llvm_orc_registerEHFrameSectionAllocAction(const char *ArgData,168                                           size_t ArgSize) {169  return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(170             ArgData, ArgSize, registerEHFrameWrapper)171      .release();172}173 174extern "C" orc::shared::CWrapperFunctionResult175llvm_orc_deregisterEHFrameSectionAllocAction(const char *ArgData,176                                             size_t ArgSize) {177  return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(178             ArgData, ArgSize, deregisterEHFrameWrapper)179      .release();180}181