Home | History | Annotate | Line # | Download | only in TargetProcess
      1 //===--------- RegisterEHFrames.cpp - Register EH frame sections ----------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
     11 
     12 #include "llvm/Config/config.h"
     13 #include "llvm/ExecutionEngine/JITSymbol.h"
     14 #include "llvm/Support/BinaryStreamReader.h"
     15 #include "llvm/Support/Compiler.h"
     16 #include "llvm/Support/Debug.h"
     17 #include "llvm/Support/DynamicLibrary.h"
     18 #include "llvm/Support/raw_ostream.h"
     19 
     20 #include "llvm/Support/FormatVariadic.h"
     21 
     22 #define DEBUG_TYPE "orc"
     23 
     24 using namespace llvm;
     25 using namespace llvm::orc;
     26 using namespace llvm::orc::tpctypes;
     27 
     28 namespace llvm {
     29 namespace orc {
     30 
     31 #if defined(HAVE_REGISTER_FRAME) && defined(HAVE_DEREGISTER_FRAME) &&          \
     32     !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
     33 
     34 extern "C" void __register_frame(const void *);
     35 extern "C" void __deregister_frame(const void *);
     36 
     37 Error registerFrameWrapper(const void *P) {
     38   __register_frame(P);
     39   return Error::success();
     40 }
     41 
     42 Error deregisterFrameWrapper(const void *P) {
     43   __deregister_frame(P);
     44   return Error::success();
     45 }
     46 
     47 #else
     48 
     49 // The building compiler does not have __(de)register_frame but
     50 // it may be found at runtime in a dynamically-loaded library.
     51 // For example, this happens when building LLVM with Visual C++
     52 // but using the MingW runtime.
     53 static Error registerFrameWrapper(const void *P) {
     54   static void((*RegisterFrame)(const void *)) = 0;
     55 
     56   if (!RegisterFrame)
     57     *(void **)&RegisterFrame =
     58         llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");
     59 
     60   if (RegisterFrame) {
     61     RegisterFrame(P);
     62     return Error::success();
     63   }
     64 
     65   return make_error<StringError>("could not register eh-frame: "
     66                                  "__register_frame function not found",
     67                                  inconvertibleErrorCode());
     68 }
     69 
     70 static Error deregisterFrameWrapper(const void *P) {
     71   static void((*DeregisterFrame)(const void *)) = 0;
     72 
     73   if (!DeregisterFrame)
     74     *(void **)&DeregisterFrame =
     75         llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
     76             "__deregister_frame");
     77 
     78   if (DeregisterFrame) {
     79     DeregisterFrame(P);
     80     return Error::success();
     81   }
     82 
     83   return make_error<StringError>("could not deregister eh-frame: "
     84                                  "__deregister_frame function not found",
     85                                  inconvertibleErrorCode());
     86 }
     87 #endif
     88 
     89 #ifdef __APPLE__
     90 
     91 template <typename HandleFDEFn>
     92 Error walkAppleEHFrameSection(const char *const SectionStart,
     93                               size_t SectionSize, HandleFDEFn HandleFDE) {
     94   const char *CurCFIRecord = SectionStart;
     95   const char *End = SectionStart + SectionSize;
     96   uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
     97 
     98   while (CurCFIRecord != End && Size != 0) {
     99     const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);
    100     if (Size == 0xffffffff)
    101       Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
    102     else
    103       Size += 4;
    104     uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
    105 
    106     LLVM_DEBUG({
    107       dbgs() << "Registering eh-frame section:\n";
    108       dbgs() << "Processing " << (Offset ? "FDE" : "CIE") << " @"
    109              << (void *)CurCFIRecord << ": [";
    110       for (unsigned I = 0; I < Size; ++I)
    111         dbgs() << format(" 0x%02" PRIx8, *(CurCFIRecord + I));
    112       dbgs() << " ]\n";
    113     });
    114 
    115     if (Offset != 0)
    116       if (auto Err = HandleFDE(CurCFIRecord))
    117         return Err;
    118 
    119     CurCFIRecord += Size;
    120 
    121     Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
    122   }
    123 
    124   return Error::success();
    125 }
    126 
    127 #endif // __APPLE__
    128 
    129 Error registerEHFrameSection(const void *EHFrameSectionAddr,
    130                              size_t EHFrameSectionSize) {
    131 #ifdef __APPLE__
    132   // On Darwin __register_frame has to be called for each FDE entry.
    133   return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
    134                                  EHFrameSectionSize, registerFrameWrapper);
    135 #else
    136   // On Linux __register_frame takes a single argument:
    137   // a pointer to the start of the .eh_frame section.
    138 
    139   // How can it find the end? Because crtendS.o is linked
    140   // in and it has an .eh_frame section with four zero chars.
    141   return registerFrameWrapper(EHFrameSectionAddr);
    142 #endif
    143 }
    144 
    145 Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
    146                                size_t EHFrameSectionSize) {
    147 #ifdef __APPLE__
    148   return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
    149                                  EHFrameSectionSize, deregisterFrameWrapper);
    150 #else
    151   return deregisterFrameWrapper(EHFrameSectionAddr);
    152 #endif
    153 }
    154 
    155 } // end namespace orc
    156 } // end namespace llvm
    157 
    158 extern "C" CWrapperFunctionResult
    159 llvm_orc_registerEHFrameSectionWrapper(uint8_t *Data, uint64_t Size) {
    160   if (Size != sizeof(uint64_t) + sizeof(uint64_t))
    161     return WrapperFunctionResult::from(
    162                "Invalid arguments to llvm_orc_registerEHFrameSectionWrapper")
    163         .release();
    164 
    165   uint64_t EHFrameSectionAddr;
    166   uint64_t EHFrameSectionSize;
    167 
    168   {
    169     BinaryStreamReader ArgReader(ArrayRef<uint8_t>(Data, Size),
    170                                  support::endianness::big);
    171     cantFail(ArgReader.readInteger(EHFrameSectionAddr));
    172     cantFail(ArgReader.readInteger(EHFrameSectionSize));
    173   }
    174 
    175   if (auto Err = registerEHFrameSection(
    176           jitTargetAddressToPointer<void *>(EHFrameSectionAddr),
    177           EHFrameSectionSize)) {
    178     auto ErrMsg = toString(std::move(Err));
    179     return WrapperFunctionResult::from(ErrMsg).release();
    180   }
    181   return WrapperFunctionResult().release();
    182 }
    183 
    184 extern "C" CWrapperFunctionResult
    185 llvm_orc_deregisterEHFrameSectionWrapper(uint8_t *Data, uint64_t Size) {
    186   if (Size != sizeof(uint64_t) + sizeof(uint64_t))
    187     return WrapperFunctionResult::from(
    188                "Invalid arguments to llvm_orc_registerEHFrameSectionWrapper")
    189         .release();
    190 
    191   uint64_t EHFrameSectionAddr;
    192   uint64_t EHFrameSectionSize;
    193 
    194   {
    195     BinaryStreamReader ArgReader(ArrayRef<uint8_t>(Data, Size),
    196                                  support::endianness::big);
    197     cantFail(ArgReader.readInteger(EHFrameSectionAddr));
    198     cantFail(ArgReader.readInteger(EHFrameSectionSize));
    199   }
    200 
    201   if (auto Err = deregisterEHFrameSection(
    202           jitTargetAddressToPointer<void *>(EHFrameSectionAddr),
    203           EHFrameSectionSize)) {
    204     auto ErrMsg = toString(std::move(Err));
    205     return WrapperFunctionResult::from(ErrMsg).release();
    206   }
    207   return WrapperFunctionResult().release();
    208 }
    209