brintos

brintos / llvm-project-archived public Read only

0
0
Text · 27.6 KiB · 4cce20e Raw
848 lines · cpp
1//===- coff_platform.cpp --------------------------------------------------===//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// This file contains code required to load the rest of the COFF runtime.10//11//===----------------------------------------------------------------------===//12 13#define NOMINMAX14#include <windows.h>15 16#include "coff_platform.h"17 18#include "debug.h"19#include "error.h"20#include "jit_dispatch.h"21#include "wrapper_function_utils.h"22 23#include <array>24#include <list>25#include <map>26#include <mutex>27#include <sstream>28#include <string_view>29#include <vector>30 31#define DEBUG_TYPE "coff_platform"32 33using namespace orc_rt;34 35namespace orc_rt {36 37using COFFJITDylibDepInfo = std::vector<ExecutorAddr>;38using COFFJITDylibDepInfoMap =39    std::unordered_map<ExecutorAddr, COFFJITDylibDepInfo>;40 41using SPSCOFFObjectSectionsMap =42    SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>;43 44using SPSCOFFJITDylibDepInfo = SPSSequence<SPSExecutorAddr>;45 46using SPSCOFFJITDylibDepInfoMap =47    SPSSequence<SPSTuple<SPSExecutorAddr, SPSCOFFJITDylibDepInfo>>;48 49} // namespace orc_rt50 51ORC_RT_JIT_DISPATCH_TAG(__orc_rt_coff_symbol_lookup_tag)52ORC_RT_JIT_DISPATCH_TAG(__orc_rt_coff_push_initializers_tag)53 54namespace {55class COFFPlatformRuntimeState {56private:57  // Ctor/dtor section.58  // Manage lists of *tor functions sorted by the last character of subsection59  // name.60  struct XtorSection {61    void Register(char SubsectionChar, span<void (*)(void)> Xtors) {62      Subsections[SubsectionChar - 'A'].push_back(Xtors);63      SubsectionsNew[SubsectionChar - 'A'].push_back(Xtors);64    }65 66    void RegisterNoRun(char SubsectionChar, span<void (*)(void)> Xtors) {67      Subsections[SubsectionChar - 'A'].push_back(Xtors);68    }69 70    void Reset() { SubsectionsNew = Subsections; }71 72    void RunAllNewAndFlush();73 74  private:75    std::array<std::vector<span<void (*)(void)>>, 26> Subsections;76    std::array<std::vector<span<void (*)(void)>>, 26> SubsectionsNew;77  };78 79  struct JITDylibState {80    std::string Name;81    void *Header = nullptr;82    size_t LinkedAgainstRefCount = 0;83    size_t DlRefCount = 0;84    std::vector<JITDylibState *> Deps;85    std::vector<void (*)(void)> AtExits;86    XtorSection CInitSection;    // XIA~XIZ87    XtorSection CXXInitSection;  // XCA~XCZ88    XtorSection CPreTermSection; // XPA~XPZ89    XtorSection CTermSection;    // XTA~XTZ90 91    bool referenced() const {92      return LinkedAgainstRefCount != 0 || DlRefCount != 0;93    }94  };95 96public:97  static void initialize();98  static COFFPlatformRuntimeState &get();99  static bool isInitialized() { return CPS; }100  static void destroy();101 102  COFFPlatformRuntimeState() = default;103 104  // Delete copy and move constructors.105  COFFPlatformRuntimeState(const COFFPlatformRuntimeState &) = delete;106  COFFPlatformRuntimeState &107  operator=(const COFFPlatformRuntimeState &) = delete;108  COFFPlatformRuntimeState(COFFPlatformRuntimeState &&) = delete;109  COFFPlatformRuntimeState &operator=(COFFPlatformRuntimeState &&) = delete;110 111  const char *dlerror();112  void *dlopen(std::string_view Name, int Mode);113  int dlupdate(void *DSOHandle);114  int dlclose(void *Header);115  void *dlsym(void *Header, std::string_view Symbol);116 117  Error registerJITDylib(std::string Name, void *Header);118  Error deregisterJITDylib(void *Header);119 120  Error registerAtExit(ExecutorAddr HeaderAddr, void (*AtExit)(void));121 122  Error registerObjectSections(123      ExecutorAddr HeaderAddr,124      std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs,125      bool RunInitializers);126  Error deregisterObjectSections(127      ExecutorAddr HeaderAddr,128      std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs);129 130  void *findJITDylibBaseByPC(uint64_t PC);131 132private:133  Error registerBlockRange(ExecutorAddr HeaderAddr, ExecutorAddrRange Range);134  Error deregisterBlockRange(ExecutorAddr HeaderAddr, ExecutorAddrRange Range);135 136  Error registerSEHFrames(ExecutorAddr HeaderAddr,137                          ExecutorAddrRange SEHFrameRange);138  Error deregisterSEHFrames(ExecutorAddr HeaderAddr,139                            ExecutorAddrRange SEHFrameRange);140 141  Expected<void *> dlopenImpl(std::string_view Path, int Mode);142  Error dlopenFull(JITDylibState &JDS);143  Error dlopenInitialize(JITDylibState &JDS, COFFJITDylibDepInfoMap &DepInfo);144 145  Error dlupdateImpl(void *DSOHandle);146  Error dlupdateFull(JITDylibState &JDS);147  Error dlupdateInitialize(JITDylibState &JDS);148 149  Error dlcloseImpl(void *DSOHandle);150  Error dlcloseDeinitialize(JITDylibState &JDS);151 152  JITDylibState *getJITDylibStateByHeader(void *DSOHandle);153  JITDylibState *getJITDylibStateByName(std::string_view Path);154  Expected<ExecutorAddr> lookupSymbolInJITDylib(void *DSOHandle,155                                                std::string_view Symbol);156 157  static COFFPlatformRuntimeState *CPS;158 159  std::recursive_mutex JDStatesMutex;160  std::map<void *, JITDylibState> JDStates;161  struct BlockRange {162    void *Header;163    size_t Size;164  };165  std::map<void *, BlockRange> BlockRanges;166  std::unordered_map<std::string_view, void *> JDNameToHeader;167  std::string DLFcnError;168};169 170} // namespace171 172COFFPlatformRuntimeState *COFFPlatformRuntimeState::CPS = nullptr;173 174COFFPlatformRuntimeState::JITDylibState *175COFFPlatformRuntimeState::getJITDylibStateByHeader(void *Header) {176  auto I = JDStates.find(Header);177  if (I == JDStates.end())178    return nullptr;179  return &I->second;180}181 182COFFPlatformRuntimeState::JITDylibState *183COFFPlatformRuntimeState::getJITDylibStateByName(std::string_view Name) {184  // FIXME: Avoid creating string copy here.185  auto I = JDNameToHeader.find(std::string(Name.data(), Name.size()));186  if (I == JDNameToHeader.end())187    return nullptr;188  void *H = I->second;189  auto J = JDStates.find(H);190  assert(J != JDStates.end() &&191         "JITDylib has name map entry but no header map entry");192  return &J->second;193}194 195Error COFFPlatformRuntimeState::registerJITDylib(std::string Name,196                                                 void *Header) {197  ORC_RT_DEBUG({198    printdbg("Registering JITDylib %s: Header = %p\n", Name.c_str(), Header);199  });200  std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);201  if (JDStates.count(Header)) {202    std::ostringstream ErrStream;203    ErrStream << "Duplicate JITDylib registration for header " << Header204              << " (name = " << Name << ")";205    return make_error<StringError>(ErrStream.str());206  }207  if (JDNameToHeader.count(Name)) {208    std::ostringstream ErrStream;209    ErrStream << "Duplicate JITDylib registration for header " << Header210              << " (header = " << Header << ")";211    return make_error<StringError>(ErrStream.str());212  }213 214  auto &JDS = JDStates[Header];215  JDS.Name = std::move(Name);216  JDS.Header = Header;217  JDNameToHeader[JDS.Name] = Header;218  return Error::success();219}220 221Error COFFPlatformRuntimeState::deregisterJITDylib(void *Header) {222  std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);223  auto I = JDStates.find(Header);224  if (I == JDStates.end()) {225    std::ostringstream ErrStream;226    ErrStream << "Attempted to deregister unrecognized header " << Header;227    return make_error<StringError>(ErrStream.str());228  }229 230  // Remove std::string construction once we can use C++20.231  auto J = JDNameToHeader.find(232      std::string(I->second.Name.data(), I->second.Name.size()));233  assert(J != JDNameToHeader.end() &&234         "Missing JDNameToHeader entry for JITDylib");235 236  ORC_RT_DEBUG({237    printdbg("Deregistering JITDylib %s: Header = %p\n", I->second.Name.c_str(),238             Header);239  });240 241  JDNameToHeader.erase(J);242  JDStates.erase(I);243  return Error::success();244}245 246void COFFPlatformRuntimeState::XtorSection::RunAllNewAndFlush() {247  for (auto &Subsection : SubsectionsNew) {248    for (auto &XtorGroup : Subsection)249      for (auto &Xtor : XtorGroup)250        if (Xtor)251          Xtor();252    Subsection.clear();253  }254}255 256const char *COFFPlatformRuntimeState::dlerror() { return DLFcnError.c_str(); }257 258void *COFFPlatformRuntimeState::dlopen(std::string_view Path, int Mode) {259  ORC_RT_DEBUG({260    std::string S(Path.data(), Path.size());261    printdbg("COFFPlatform::dlopen(\"%s\")\n", S.c_str());262  });263  std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);264  if (auto H = dlopenImpl(Path, Mode))265    return *H;266  else {267    // FIXME: Make dlerror thread safe.268    DLFcnError = toString(H.takeError());269    return nullptr;270  }271}272 273int COFFPlatformRuntimeState::dlupdate(void *DSOHandle) {274  ORC_RT_DEBUG({275    std::string S;276    printdbg("COFFPlatform::dlupdate(%p) (%s)\n", DSOHandle, S.c_str());277  });278  std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);279  if (auto Err = dlupdateImpl(DSOHandle)) {280    // FIXME: Make dlerror thread safe.281    DLFcnError = toString(std::move(Err));282    return -1;283  }284  return 0;285}286 287int COFFPlatformRuntimeState::dlclose(void *DSOHandle) {288  ORC_RT_DEBUG({289    auto *JDS = getJITDylibStateByHeader(DSOHandle);290    std::string DylibName;291    if (JDS) {292      std::string S;293      printdbg("COFFPlatform::dlclose(%p) (%s)\n", DSOHandle, S.c_str());294    } else295      printdbg("COFFPlatform::dlclose(%p) (%s)\n", DSOHandle, "invalid handle");296  });297  std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);298  if (auto Err = dlcloseImpl(DSOHandle)) {299    // FIXME: Make dlerror thread safe.300    DLFcnError = toString(std::move(Err));301    return -1;302  }303  return 0;304}305 306void *COFFPlatformRuntimeState::dlsym(void *Header, std::string_view Symbol) {307  auto Addr = lookupSymbolInJITDylib(Header, Symbol);308  if (!Addr) {309    return 0;310  }311 312  return Addr->toPtr<void *>();313}314 315Expected<void *> COFFPlatformRuntimeState::dlopenImpl(std::string_view Path,316                                                      int Mode) {317  // Try to find JITDylib state by name.318  auto *JDS = getJITDylibStateByName(Path);319 320  if (!JDS)321    return make_error<StringError>("No registered JTIDylib for path " +322                                   std::string(Path.data(), Path.size()));323 324  if (auto Err = dlopenFull(*JDS))325    return std::move(Err);326 327  // Bump the ref-count on this dylib.328  ++JDS->DlRefCount;329 330  // Return the header address.331  return JDS->Header;332}333 334Error COFFPlatformRuntimeState::dlopenFull(JITDylibState &JDS) {335  // Call back to the JIT to push the initializers.336  Expected<COFFJITDylibDepInfoMap> DepInfoMap((COFFJITDylibDepInfoMap()));337  if (auto Err = WrapperFunction<SPSExpected<SPSCOFFJITDylibDepInfoMap>(338          SPSExecutorAddr)>::339          call(JITDispatch(&__orc_rt_coff_push_initializers_tag), DepInfoMap,340               ExecutorAddr::fromPtr(JDS.Header)))341    return Err;342  if (!DepInfoMap)343    return DepInfoMap.takeError();344 345  if (auto Err = dlopenInitialize(JDS, *DepInfoMap))346    return Err;347 348  if (!DepInfoMap->empty()) {349    ORC_RT_DEBUG({350      printdbg("Unrecognized dep-info key headers in dlopen of %s\n",351               JDS.Name.c_str());352    });353    std::ostringstream ErrStream;354    ErrStream << "Encountered unrecognized dep-info key headers "355                 "while processing dlopen of "356              << JDS.Name;357    return make_error<StringError>(ErrStream.str());358  }359 360  return Error::success();361}362 363Error COFFPlatformRuntimeState::dlopenInitialize(364    JITDylibState &JDS, COFFJITDylibDepInfoMap &DepInfo) {365  ORC_RT_DEBUG({366    printdbg("COFFPlatformRuntimeState::dlopenInitialize(\"%s\")\n",367             JDS.Name.c_str());368  });369 370  // Skip visited dependency.371  auto I = DepInfo.find(ExecutorAddr::fromPtr(JDS.Header));372  if (I == DepInfo.end())373    return Error::success();374 375  auto DI = std::move(I->second);376  DepInfo.erase(I);377 378  // Run initializers of dependencies in proper order by depth-first traversal379  // of dependency graph.380  std::vector<JITDylibState *> OldDeps;381  std::swap(JDS.Deps, OldDeps);382  JDS.Deps.reserve(DI.size());383  for (auto DepHeaderAddr : DI) {384    auto *DepJDS = getJITDylibStateByHeader(DepHeaderAddr.toPtr<void *>());385    if (!DepJDS) {386      std::ostringstream ErrStream;387      ErrStream << "Encountered unrecognized dep header "388                << DepHeaderAddr.toPtr<void *>() << " while initializing "389                << JDS.Name;390      return make_error<StringError>(ErrStream.str());391    }392    ++DepJDS->LinkedAgainstRefCount;393    if (auto Err = dlopenInitialize(*DepJDS, DepInfo))394      return Err;395  }396 397  // Run static initializers.398  JDS.CInitSection.RunAllNewAndFlush();399  JDS.CXXInitSection.RunAllNewAndFlush();400 401  // Decrement old deps.402  for (auto *DepJDS : OldDeps) {403    --DepJDS->LinkedAgainstRefCount;404    if (!DepJDS->referenced())405      if (auto Err = dlcloseDeinitialize(*DepJDS))406        return Err;407  }408 409  return Error::success();410}411 412Error COFFPlatformRuntimeState::dlupdateImpl(void *DSOHandle) {413  // Try to find JITDylib state by header.414  auto *JDS = getJITDylibStateByHeader(DSOHandle);415 416  if (!JDS) {417    std::ostringstream ErrStream;418    ErrStream << "No registered JITDylib for " << DSOHandle;419    return make_error<StringError>(ErrStream.str());420  }421 422  if (!JDS->referenced())423    return make_error<StringError>("dlupdate failed, JITDylib must be open.");424 425  if (auto Err = dlupdateFull(*JDS))426    return Err;427 428  return Error::success();429}430 431Error COFFPlatformRuntimeState::dlupdateFull(JITDylibState &JDS) {432  // Call back to the JIT to push the initializers.433  Expected<COFFJITDylibDepInfoMap> DepInfoMap((COFFJITDylibDepInfoMap()));434  if (auto Err = WrapperFunction<SPSExpected<SPSCOFFJITDylibDepInfoMap>(435          SPSExecutorAddr)>::436          call(JITDispatch(&__orc_rt_coff_push_initializers_tag), DepInfoMap,437               ExecutorAddr::fromPtr(JDS.Header)))438    return Err;439  if (!DepInfoMap)440    return DepInfoMap.takeError();441 442  if (auto Err = dlupdateInitialize(JDS))443    return Err;444 445  return Error::success();446}447 448Error COFFPlatformRuntimeState::dlupdateInitialize(JITDylibState &JDS) {449  ORC_RT_DEBUG({450    printdbg("COFFPlatformRuntimeState::dlupdateInitialize(\"%s\")\n",451             JDS.Name.c_str());452  });453 454  // Run static initializers.455  JDS.CInitSection.RunAllNewAndFlush();456  JDS.CXXInitSection.RunAllNewAndFlush();457 458  return Error::success();459}460 461Error COFFPlatformRuntimeState::dlcloseImpl(void *DSOHandle) {462  // Try to find JITDylib state by header.463  auto *JDS = getJITDylibStateByHeader(DSOHandle);464 465  if (!JDS) {466    std::ostringstream ErrStream;467    ErrStream << "No registered JITDylib for " << DSOHandle;468    return make_error<StringError>(ErrStream.str());469  }470 471  // Bump the ref-count.472  --JDS->DlRefCount;473 474  if (!JDS->referenced())475    return dlcloseDeinitialize(*JDS);476 477  return Error::success();478}479 480Error COFFPlatformRuntimeState::dlcloseDeinitialize(JITDylibState &JDS) {481  ORC_RT_DEBUG({482    printdbg("COFFPlatformRuntimeState::dlcloseDeinitialize(\"%s\")\n",483             JDS.Name.c_str());484  });485 486  // Run atexits487  for (auto AtExit : JDS.AtExits)488    AtExit();489  JDS.AtExits.clear();490 491  // Run static terminators.492  JDS.CPreTermSection.RunAllNewAndFlush();493  JDS.CTermSection.RunAllNewAndFlush();494 495  // Queue all xtors as new again.496  JDS.CInitSection.Reset();497  JDS.CXXInitSection.Reset();498  JDS.CPreTermSection.Reset();499  JDS.CTermSection.Reset();500 501  // Deinitialize any dependencies.502  for (auto *DepJDS : JDS.Deps) {503    --DepJDS->LinkedAgainstRefCount;504    if (!DepJDS->referenced())505      if (auto Err = dlcloseDeinitialize(*DepJDS))506        return Err;507  }508 509  return Error::success();510}511 512Expected<ExecutorAddr>513COFFPlatformRuntimeState::lookupSymbolInJITDylib(void *header,514                                                 std::string_view Sym) {515  Expected<ExecutorAddr> Result((ExecutorAddr()));516  if (auto Err = WrapperFunction<SPSExpected<SPSExecutorAddr>(517          SPSExecutorAddr,518          SPSString)>::call(JITDispatch(&__orc_rt_coff_symbol_lookup_tag),519                            Result, ExecutorAddr::fromPtr(header), Sym))520    return std::move(Err);521  return Result;522}523 524Error COFFPlatformRuntimeState::registerObjectSections(525    ExecutorAddr HeaderAddr,526    std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs,527    bool RunInitializers) {528  std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);529  auto I = JDStates.find(HeaderAddr.toPtr<void *>());530  if (I == JDStates.end()) {531    std::ostringstream ErrStream;532    ErrStream << "Unrecognized header " << HeaderAddr.getValue();533    return make_error<StringError>(ErrStream.str());534  }535  auto &JDState = I->second;536  for (auto &KV : Secs) {537    if (auto Err = registerBlockRange(HeaderAddr, KV.second))538      return Err;539    if (KV.first.empty())540      continue;541    char LastChar = KV.first.data()[KV.first.size() - 1];542    if (KV.first == ".pdata") {543      if (auto Err = registerSEHFrames(HeaderAddr, KV.second))544        return Err;545    } else if (KV.first >= ".CRT$XIA" && KV.first <= ".CRT$XIZ") {546      if (RunInitializers)547        JDState.CInitSection.Register(LastChar,548                                      KV.second.toSpan<void (*)(void)>());549      else550        JDState.CInitSection.RegisterNoRun(LastChar,551                                           KV.second.toSpan<void (*)(void)>());552    } else if (KV.first >= ".CRT$XCA" && KV.first <= ".CRT$XCZ") {553      if (RunInitializers)554        JDState.CXXInitSection.Register(LastChar,555                                        KV.second.toSpan<void (*)(void)>());556      else557        JDState.CXXInitSection.RegisterNoRun(558            LastChar, KV.second.toSpan<void (*)(void)>());559    } else if (KV.first >= ".CRT$XPA" && KV.first <= ".CRT$XPZ")560      JDState.CPreTermSection.Register(LastChar,561                                       KV.second.toSpan<void (*)(void)>());562    else if (KV.first >= ".CRT$XTA" && KV.first <= ".CRT$XTZ")563      JDState.CTermSection.Register(LastChar,564                                    KV.second.toSpan<void (*)(void)>());565  }566  return Error::success();567}568 569Error COFFPlatformRuntimeState::deregisterObjectSections(570    ExecutorAddr HeaderAddr,571    std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs) {572  std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);573  auto I = JDStates.find(HeaderAddr.toPtr<void *>());574  if (I == JDStates.end()) {575    std::ostringstream ErrStream;576    ErrStream << "Attempted to deregister unrecognized header "577              << HeaderAddr.getValue();578    return make_error<StringError>(ErrStream.str());579  }580  for (auto &KV : Secs) {581    if (auto Err = deregisterBlockRange(HeaderAddr, KV.second))582      return Err;583    if (KV.first == ".pdata")584      if (auto Err = deregisterSEHFrames(HeaderAddr, KV.second))585        return Err;586  }587  return Error::success();588}589 590Error COFFPlatformRuntimeState::registerSEHFrames(591    ExecutorAddr HeaderAddr, ExecutorAddrRange SEHFrameRange) {592  int N = (SEHFrameRange.End.getValue() - SEHFrameRange.Start.getValue()) /593          sizeof(RUNTIME_FUNCTION);594  auto Func = SEHFrameRange.Start.toPtr<PRUNTIME_FUNCTION>();595  if (!RtlAddFunctionTable(Func, N,596                           static_cast<DWORD64>(HeaderAddr.getValue())))597    return make_error<StringError>("Failed to register SEH frames");598  return Error::success();599}600 601Error COFFPlatformRuntimeState::deregisterSEHFrames(602    ExecutorAddr HeaderAddr, ExecutorAddrRange SEHFrameRange) {603  if (!RtlDeleteFunctionTable(SEHFrameRange.Start.toPtr<PRUNTIME_FUNCTION>()))604    return make_error<StringError>("Failed to deregister SEH frames");605  return Error::success();606}607 608Error COFFPlatformRuntimeState::registerBlockRange(ExecutorAddr HeaderAddr,609                                                   ExecutorAddrRange Range) {610  assert(!BlockRanges.count(Range.Start.toPtr<void *>()) &&611         "Block range address already registered");612  BlockRange B = {HeaderAddr.toPtr<void *>(), Range.size()};613  BlockRanges.emplace(Range.Start.toPtr<void *>(), B);614  return Error::success();615}616 617Error COFFPlatformRuntimeState::deregisterBlockRange(ExecutorAddr HeaderAddr,618                                                     ExecutorAddrRange Range) {619  assert(BlockRanges.count(Range.Start.toPtr<void *>()) &&620         "Block range address not registered");621  BlockRanges.erase(Range.Start.toPtr<void *>());622  return Error::success();623}624 625Error COFFPlatformRuntimeState::registerAtExit(ExecutorAddr HeaderAddr,626                                               void (*AtExit)(void)) {627  std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);628  auto I = JDStates.find(HeaderAddr.toPtr<void *>());629  if (I == JDStates.end()) {630    std::ostringstream ErrStream;631    ErrStream << "Unrecognized header " << HeaderAddr.getValue();632    return make_error<StringError>(ErrStream.str());633  }634  I->second.AtExits.push_back(AtExit);635  return Error::success();636}637 638void COFFPlatformRuntimeState::initialize() {639  assert(!CPS && "COFFPlatformRuntimeState should be null");640  CPS = new COFFPlatformRuntimeState();641}642 643COFFPlatformRuntimeState &COFFPlatformRuntimeState::get() {644  assert(CPS && "COFFPlatformRuntimeState not initialized");645  return *CPS;646}647 648void COFFPlatformRuntimeState::destroy() {649  assert(CPS && "COFFPlatformRuntimeState not initialized");650  delete CPS;651}652 653void *COFFPlatformRuntimeState::findJITDylibBaseByPC(uint64_t PC) {654  std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);655  auto It = BlockRanges.upper_bound(reinterpret_cast<void *>(PC));656  if (It == BlockRanges.begin())657    return nullptr;658  --It;659  auto &Range = It->second;660  if (PC >= reinterpret_cast<uint64_t>(It->first) + Range.Size)661    return nullptr;662  return Range.Header;663}664 665ORC_RT_INTERFACE orc_rt_WrapperFunctionResult666__orc_rt_coff_platform_bootstrap(char *ArgData, size_t ArgSize) {667  COFFPlatformRuntimeState::initialize();668  return WrapperFunctionResult().release();669}670 671ORC_RT_INTERFACE orc_rt_WrapperFunctionResult672__orc_rt_coff_platform_shutdown(char *ArgData, size_t ArgSize) {673  COFFPlatformRuntimeState::destroy();674  return WrapperFunctionResult().release();675}676 677ORC_RT_INTERFACE orc_rt_WrapperFunctionResult678__orc_rt_coff_register_jitdylib(char *ArgData, size_t ArgSize) {679  return WrapperFunction<SPSError(SPSString, SPSExecutorAddr)>::handle(680             ArgData, ArgSize,681             [](std::string &Name, ExecutorAddr HeaderAddr) {682               return COFFPlatformRuntimeState::get().registerJITDylib(683                   std::move(Name), HeaderAddr.toPtr<void *>());684             })685      .release();686}687 688ORC_RT_INTERFACE orc_rt_WrapperFunctionResult689__orc_rt_coff_deregister_jitdylib(char *ArgData, size_t ArgSize) {690  return WrapperFunction<SPSError(SPSExecutorAddr)>::handle(691             ArgData, ArgSize,692             [](ExecutorAddr HeaderAddr) {693               return COFFPlatformRuntimeState::get().deregisterJITDylib(694                   HeaderAddr.toPtr<void *>());695             })696      .release();697}698 699ORC_RT_INTERFACE orc_rt_WrapperFunctionResult700__orc_rt_coff_register_object_sections(char *ArgData, size_t ArgSize) {701  return WrapperFunction<SPSError(SPSExecutorAddr, SPSCOFFObjectSectionsMap,702                                  bool)>::703      handle(ArgData, ArgSize,704             [](ExecutorAddr HeaderAddr,705                std::vector<std::pair<std::string_view, ExecutorAddrRange>>706                    &Secs,707                bool RunInitializers) {708               return COFFPlatformRuntimeState::get().registerObjectSections(709                   HeaderAddr, std::move(Secs), RunInitializers);710             })711          .release();712}713 714ORC_RT_INTERFACE orc_rt_WrapperFunctionResult715__orc_rt_coff_deregister_object_sections(char *ArgData, size_t ArgSize) {716  return WrapperFunction<SPSError(SPSExecutorAddr, SPSCOFFObjectSectionsMap)>::717      handle(ArgData, ArgSize,718             [](ExecutorAddr HeaderAddr,719                std::vector<std::pair<std::string_view, ExecutorAddrRange>>720                    &Secs) {721               return COFFPlatformRuntimeState::get().deregisterObjectSections(722                   HeaderAddr, std::move(Secs));723             })724          .release();725}726//------------------------------------------------------------------------------727//                        JIT'd dlfcn alternatives.728//------------------------------------------------------------------------------729 730const char *__orc_rt_coff_jit_dlerror() {731  return COFFPlatformRuntimeState::get().dlerror();732}733 734void *__orc_rt_coff_jit_dlopen(const char *path, int mode) {735  return COFFPlatformRuntimeState::get().dlopen(path, mode);736}737 738int __orc_rt_coff_jit_dlupdate(void *dso_handle) {739  return COFFPlatformRuntimeState::get().dlupdate(dso_handle);740}741 742int __orc_rt_coff_jit_dlclose(void *header) {743  return COFFPlatformRuntimeState::get().dlclose(header);744}745 746void *__orc_rt_coff_jit_dlsym(void *header, const char *symbol) {747  return COFFPlatformRuntimeState::get().dlsym(header, symbol);748}749 750//------------------------------------------------------------------------------751//                        COFF SEH exception support752//------------------------------------------------------------------------------753 754struct ThrowInfo {755  uint32_t attributes;756  void *data;757};758 759ORC_RT_INTERFACE void __stdcall __orc_rt_coff_cxx_throw_exception(760    void *pExceptionObject, ThrowInfo *pThrowInfo) {761#ifdef __clang__762#pragma clang diagnostic push763#pragma clang diagnostic ignored "-Wmultichar"764#endif765  constexpr uint32_t EH_EXCEPTION_NUMBER = 'msc' | 0xE0000000;766#ifdef __clang__767#pragma clang diagnostic pop768#endif769  constexpr uint32_t EH_MAGIC_NUMBER1 = 0x19930520;770  auto BaseAddr = COFFPlatformRuntimeState::get().findJITDylibBaseByPC(771      reinterpret_cast<uint64_t>(pThrowInfo));772  if (!BaseAddr) {773    // This is not from JIT'd region.774    // FIXME: Use the default implementation like below when alias api is775    // capable. _CxxThrowException(pExceptionObject, pThrowInfo);776    fprintf(stderr, "Throwing exception from compiled callback into JIT'd "777                    "exception handler not supported yet.\n");778    abort();779    return;780  }781  const ULONG_PTR parameters[] = {782      EH_MAGIC_NUMBER1,783      reinterpret_cast<ULONG_PTR>(pExceptionObject),784      reinterpret_cast<ULONG_PTR>(pThrowInfo),785      reinterpret_cast<ULONG_PTR>(BaseAddr),786  };787  RaiseException(EH_EXCEPTION_NUMBER, EXCEPTION_NONCONTINUABLE,788                 _countof(parameters), parameters);789}790 791//------------------------------------------------------------------------------792//                             COFF atexits793//------------------------------------------------------------------------------794 795typedef int (*OnExitFunction)(void);796typedef void (*AtExitFunction)(void);797 798ORC_RT_INTERFACE OnExitFunction __orc_rt_coff_onexit(void *Header,799                                                     OnExitFunction Func) {800  if (auto Err = COFFPlatformRuntimeState::get().registerAtExit(801          ExecutorAddr::fromPtr(Header), (void (*)(void))Func)) {802    consumeError(std::move(Err));803    return nullptr;804  }805  return Func;806}807 808ORC_RT_INTERFACE int __orc_rt_coff_atexit(void *Header, AtExitFunction Func) {809  if (auto Err = COFFPlatformRuntimeState::get().registerAtExit(810          ExecutorAddr::fromPtr(Header), (void (*)(void))Func)) {811    consumeError(std::move(Err));812    return -1;813  }814  return 0;815}816 817//------------------------------------------------------------------------------818//                             COFF Run Program819//------------------------------------------------------------------------------820 821ORC_RT_INTERFACE int64_t __orc_rt_coff_run_program(const char *JITDylibName,822                                                   const char *EntrySymbolName,823                                                   int argc, char *argv[]) {824  using MainTy = int (*)(int, char *[]);825 826  void *H =827      __orc_rt_coff_jit_dlopen(JITDylibName, orc_rt::coff::ORC_RT_RTLD_LAZY);828  if (!H) {829    __orc_rt_log_error(__orc_rt_coff_jit_dlerror());830    return -1;831  }832 833  auto *Main =834      reinterpret_cast<MainTy>(__orc_rt_coff_jit_dlsym(H, EntrySymbolName));835 836  if (!Main) {837    __orc_rt_log_error(__orc_rt_coff_jit_dlerror());838    return -1;839  }840 841  int Result = Main(argc, argv);842 843  if (__orc_rt_coff_jit_dlclose(H) == -1)844    __orc_rt_log_error(__orc_rt_coff_jit_dlerror());845 846  return Result;847}848