Path: blob/main/contrib/llvm-project/compiler-rt/lib/orc/macho_platform.cpp
39566 views
//===- macho_platform.cpp -------------------------------------------------===//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//===----------------------------------------------------------------------===//7//8// This file contains code required to load the rest of the MachO runtime.9//10//===----------------------------------------------------------------------===//1112#include "macho_platform.h"13#include "bitmask_enum.h"14#include "common.h"15#include "debug.h"16#include "error.h"17#include "interval_map.h"18#include "wrapper_function_utils.h"1920#include <algorithm>21#include <ios>22#include <map>23#include <mutex>24#include <sstream>25#include <string_view>26#include <unordered_map>27#include <unordered_set>28#include <vector>2930#define DEBUG_TYPE "macho_platform"3132using namespace __orc_rt;33using namespace __orc_rt::macho;3435// Declare function tags for functions in the JIT process.36ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_push_initializers_tag)37ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_push_symbols_tag)3839struct objc_image_info;40struct mach_header;4142// Objective-C registration functions.43// These are weakly imported. If the Objective-C runtime has not been loaded44// then code containing Objective-C sections will generate an error.45extern "C" void46_objc_map_images(unsigned count, const char *const paths[],47const mach_header *const mhdrs[]) ORC_RT_WEAK_IMPORT;4849extern "C" void _objc_load_image(const char *path,50const mach_header *mh) ORC_RT_WEAK_IMPORT;5152// Libunwind prototypes.53struct unw_dynamic_unwind_sections {54uintptr_t dso_base;55uintptr_t dwarf_section;56size_t dwarf_section_length;57uintptr_t compact_unwind_section;58size_t compact_unwind_section_length;59};6061typedef int (*unw_find_dynamic_unwind_sections)(62uintptr_t addr, struct unw_dynamic_unwind_sections *info);6364extern "C" int __unw_add_find_dynamic_unwind_sections(65unw_find_dynamic_unwind_sections find_dynamic_unwind_sections)66ORC_RT_WEAK_IMPORT;6768extern "C" int __unw_remove_find_dynamic_unwind_sections(69unw_find_dynamic_unwind_sections find_dynamic_unwind_sections)70ORC_RT_WEAK_IMPORT;7172namespace {7374struct MachOJITDylibDepInfo {75bool Sealed = false;76std::vector<ExecutorAddr> DepHeaders;77};7879using MachOJITDylibDepInfoMap =80std::unordered_map<ExecutorAddr, MachOJITDylibDepInfo>;8182} // anonymous namespace8384namespace __orc_rt {8586using SPSMachOObjectPlatformSectionsMap =87SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>;8889using SPSMachOJITDylibDepInfo = SPSTuple<bool, SPSSequence<SPSExecutorAddr>>;9091using SPSMachOJITDylibDepInfoMap =92SPSSequence<SPSTuple<SPSExecutorAddr, SPSMachOJITDylibDepInfo>>;9394template <>95class SPSSerializationTraits<SPSMachOJITDylibDepInfo, MachOJITDylibDepInfo> {96public:97static size_t size(const MachOJITDylibDepInfo &JDI) {98return SPSMachOJITDylibDepInfo::AsArgList::size(JDI.Sealed, JDI.DepHeaders);99}100101static bool serialize(SPSOutputBuffer &OB, const MachOJITDylibDepInfo &JDI) {102return SPSMachOJITDylibDepInfo::AsArgList::serialize(OB, JDI.Sealed,103JDI.DepHeaders);104}105106static bool deserialize(SPSInputBuffer &IB, MachOJITDylibDepInfo &JDI) {107return SPSMachOJITDylibDepInfo::AsArgList::deserialize(IB, JDI.Sealed,108JDI.DepHeaders);109}110};111112struct UnwindSectionInfo {113std::vector<ExecutorAddrRange> CodeRanges;114ExecutorAddrRange DwarfSection;115ExecutorAddrRange CompactUnwindSection;116};117118using SPSUnwindSectionInfo =119SPSTuple<SPSSequence<SPSExecutorAddrRange>, SPSExecutorAddrRange,120SPSExecutorAddrRange>;121122template <>123class SPSSerializationTraits<SPSUnwindSectionInfo, UnwindSectionInfo> {124public:125static size_t size(const UnwindSectionInfo &USI) {126return SPSUnwindSectionInfo::AsArgList::size(127USI.CodeRanges, USI.DwarfSection, USI.CompactUnwindSection);128}129130static bool serialize(SPSOutputBuffer &OB, const UnwindSectionInfo &USI) {131return SPSUnwindSectionInfo::AsArgList::serialize(132OB, USI.CodeRanges, USI.DwarfSection, USI.CompactUnwindSection);133}134135static bool deserialize(SPSInputBuffer &IB, UnwindSectionInfo &USI) {136return SPSUnwindSectionInfo::AsArgList::deserialize(137IB, USI.CodeRanges, USI.DwarfSection, USI.CompactUnwindSection);138}139};140141} // namespace __orc_rt142143namespace {144struct TLVDescriptor {145void *(*Thunk)(TLVDescriptor *) = nullptr;146unsigned long Key = 0;147unsigned long DataAddress = 0;148};149150class MachOPlatformRuntimeState {151public:152// Used internally by MachOPlatformRuntimeState, but made public to enable153// serialization.154enum class MachOExecutorSymbolFlags : uint8_t {155None = 0,156Weak = 1U << 0,157Callable = 1U << 1,158ORC_RT_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Callable)159};160161private:162struct AtExitEntry {163void (*Func)(void *);164void *Arg;165};166167using AtExitsVector = std::vector<AtExitEntry>;168169/// Used to manage sections of fixed-sized metadata records (e.g. pointer170/// sections, selector refs, etc.)171template <typename RecordElement> class RecordSectionsTracker {172public:173/// Add a section to the "new" list.174void add(span<RecordElement> Sec) { New.push_back(std::move(Sec)); }175176/// Returns true if there are new sections to process.177bool hasNewSections() const { return !New.empty(); }178179/// Returns the number of new sections to process.180size_t numNewSections() const { return New.size(); }181182/// Process all new sections.183template <typename ProcessSectionFunc>184std::enable_if_t<std::is_void_v<185std::invoke_result_t<ProcessSectionFunc, span<RecordElement>>>>186processNewSections(ProcessSectionFunc &&ProcessSection) {187for (auto &Sec : New)188ProcessSection(Sec);189moveNewToProcessed();190}191192/// Proces all new sections with a fallible handler.193///194/// Successfully handled sections will be moved to the Processed195/// list.196template <typename ProcessSectionFunc>197std::enable_if_t<198std::is_same_v<Error, std::invoke_result_t<ProcessSectionFunc,199span<RecordElement>>>,200Error>201processNewSections(ProcessSectionFunc &&ProcessSection) {202for (size_t I = 0; I != New.size(); ++I) {203if (auto Err = ProcessSection(New[I])) {204for (size_t J = 0; J != I; ++J)205Processed.push_back(New[J]);206New.erase(New.begin(), New.begin() + I);207return Err;208}209}210moveNewToProcessed();211return Error::success();212}213214/// Move all sections back to New for reprocessing.215void reset() {216moveNewToProcessed();217New = std::move(Processed);218}219220/// Remove the section with the given range.221bool removeIfPresent(ExecutorAddrRange R) {222if (removeIfPresent(New, R))223return true;224return removeIfPresent(Processed, R);225}226227private:228void moveNewToProcessed() {229if (Processed.empty())230Processed = std::move(New);231else {232Processed.reserve(Processed.size() + New.size());233std::copy(New.begin(), New.end(), std::back_inserter(Processed));234New.clear();235}236}237238bool removeIfPresent(std::vector<span<RecordElement>> &V,239ExecutorAddrRange R) {240auto RI = std::find_if(241V.rbegin(), V.rend(),242[RS = R.toSpan<RecordElement>()](const span<RecordElement> &E) {243return E.data() == RS.data();244});245if (RI != V.rend()) {246V.erase(std::next(RI).base());247return true;248}249return false;250}251252std::vector<span<RecordElement>> Processed;253std::vector<span<RecordElement>> New;254};255256struct UnwindSections {257UnwindSections(const UnwindSectionInfo &USI)258: DwarfSection(USI.DwarfSection.toSpan<char>()),259CompactUnwindSection(USI.CompactUnwindSection.toSpan<char>()) {}260261span<char> DwarfSection;262span<char> CompactUnwindSection;263};264265using UnwindSectionsMap =266IntervalMap<char *, UnwindSections, IntervalCoalescing::Disabled>;267268struct JITDylibState {269270using SymbolTableMap =271std::unordered_map<std::string_view,272std::pair<ExecutorAddr, MachOExecutorSymbolFlags>>;273274std::string Name;275void *Header = nullptr;276bool Sealed = false;277size_t LinkedAgainstRefCount = 0;278size_t DlRefCount = 0;279SymbolTableMap SymbolTable;280std::vector<JITDylibState *> Deps;281AtExitsVector AtExits;282const objc_image_info *ObjCImageInfo = nullptr;283std::unordered_map<void *, std::vector<char>> DataSectionContent;284std::unordered_map<void *, size_t> ZeroInitRanges;285UnwindSectionsMap UnwindSections;286RecordSectionsTracker<void (*)()> ModInitsSections;287RecordSectionsTracker<char> ObjCRuntimeRegistrationObjects;288289bool referenced() const {290return LinkedAgainstRefCount != 0 || DlRefCount != 0;291}292};293294public:295static Error create();296static MachOPlatformRuntimeState &get();297static Error destroy();298299MachOPlatformRuntimeState() = default;300301// Delete copy and move constructors.302MachOPlatformRuntimeState(const MachOPlatformRuntimeState &) = delete;303MachOPlatformRuntimeState &304operator=(const MachOPlatformRuntimeState &) = delete;305MachOPlatformRuntimeState(MachOPlatformRuntimeState &&) = delete;306MachOPlatformRuntimeState &operator=(MachOPlatformRuntimeState &&) = delete;307308Error initialize();309Error shutdown();310311Error registerJITDylib(std::string Name, void *Header);312Error deregisterJITDylib(void *Header);313Error registerThreadDataSection(span<const char> ThreadDataSection);314Error deregisterThreadDataSection(span<const char> ThreadDataSection);315Error registerObjectSymbolTable(316ExecutorAddr HeaderAddr,317const std::vector<std::tuple<ExecutorAddr, ExecutorAddr,318MachOExecutorSymbolFlags>> &Entries);319Error deregisterObjectSymbolTable(320ExecutorAddr HeaderAddr,321const std::vector<std::tuple<ExecutorAddr, ExecutorAddr,322MachOExecutorSymbolFlags>> &Entries);323Error registerObjectPlatformSections(324ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> UnwindSections,325std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs);326Error deregisterObjectPlatformSections(327ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> UnwindSections,328std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs);329330const char *dlerror();331void *dlopen(std::string_view Name, int Mode);332int dlclose(void *DSOHandle);333void *dlsym(void *DSOHandle, const char *Symbol);334335int registerAtExit(void (*F)(void *), void *Arg, void *DSOHandle);336void runAtExits(std::unique_lock<std::mutex> &JDStatesLock,337JITDylibState &JDS);338void runAtExits(void *DSOHandle);339340/// Returns the base address of the section containing ThreadData.341Expected<std::pair<const char *, size_t>>342getThreadDataSectionFor(const char *ThreadData);343344private:345JITDylibState *getJITDylibStateByHeader(void *DSOHandle);346JITDylibState *getJITDylibStateByName(std::string_view Path);347348/// Requests materialization of the given symbols. For each pair, the bool349/// element indicates whether the symbol is required (true) or weakly350/// referenced (false).351Error requestPushSymbols(JITDylibState &JDS,352span<std::pair<std::string_view, bool>> Symbols);353354/// Attempts to look up the given symbols locally, requesting a push from the355/// remote if they're not found. Results are written to the Result span, which356/// must have the same size as the Symbols span.357Error358lookupSymbols(JITDylibState &JDS, std::unique_lock<std::mutex> &JDStatesLock,359span<std::pair<ExecutorAddr, MachOExecutorSymbolFlags>> Result,360span<std::pair<std::string_view, bool>> Symbols);361362bool lookupUnwindSections(void *Addr, unw_dynamic_unwind_sections &Info);363364static int findDynamicUnwindSections(uintptr_t addr,365unw_dynamic_unwind_sections *info);366static Error registerEHFrames(span<const char> EHFrameSection);367static Error deregisterEHFrames(span<const char> EHFrameSection);368369static Error registerObjCRegistrationObjects(JITDylibState &JDS);370static Error runModInits(std::unique_lock<std::mutex> &JDStatesLock,371JITDylibState &JDS);372373Expected<void *> dlopenImpl(std::string_view Path, int Mode);374Error dlopenFull(std::unique_lock<std::mutex> &JDStatesLock,375JITDylibState &JDS);376Error dlopenInitialize(std::unique_lock<std::mutex> &JDStatesLock,377JITDylibState &JDS, MachOJITDylibDepInfoMap &DepInfo);378379Error dlcloseImpl(void *DSOHandle);380Error dlcloseDeinitialize(std::unique_lock<std::mutex> &JDStatesLock,381JITDylibState &JDS);382383static MachOPlatformRuntimeState *MOPS;384385bool UseCallbackStyleUnwindInfo = false;386387// FIXME: Move to thread-state.388std::string DLFcnError;389390// APIMutex guards against concurrent entry into key "dyld" API functions391// (e.g. dlopen, dlclose).392std::recursive_mutex DyldAPIMutex;393394// JDStatesMutex guards the data structures that hold JITDylib state.395std::mutex JDStatesMutex;396std::unordered_map<void *, JITDylibState> JDStates;397std::unordered_map<std::string_view, void *> JDNameToHeader;398399// ThreadDataSectionsMutex guards thread local data section state.400std::mutex ThreadDataSectionsMutex;401std::map<const char *, size_t> ThreadDataSections;402};403404} // anonymous namespace405406namespace __orc_rt {407408class SPSMachOExecutorSymbolFlags;409410template <>411class SPSSerializationTraits<412SPSMachOExecutorSymbolFlags,413MachOPlatformRuntimeState::MachOExecutorSymbolFlags> {414private:415using UT = std::underlying_type_t<416MachOPlatformRuntimeState::MachOExecutorSymbolFlags>;417418public:419static size_t420size(const MachOPlatformRuntimeState::MachOExecutorSymbolFlags &SF) {421return sizeof(UT);422}423424static bool425serialize(SPSOutputBuffer &OB,426const MachOPlatformRuntimeState::MachOExecutorSymbolFlags &SF) {427return SPSArgList<UT>::serialize(OB, static_cast<UT>(SF));428}429430static bool431deserialize(SPSInputBuffer &IB,432MachOPlatformRuntimeState::MachOExecutorSymbolFlags &SF) {433UT Tmp;434if (!SPSArgList<UT>::deserialize(IB, Tmp))435return false;436SF = static_cast<MachOPlatformRuntimeState::MachOExecutorSymbolFlags>(Tmp);437return true;438}439};440441} // namespace __orc_rt442443namespace {444445MachOPlatformRuntimeState *MachOPlatformRuntimeState::MOPS = nullptr;446447Error MachOPlatformRuntimeState::create() {448assert(!MOPS && "MachOPlatformRuntimeState should be null");449MOPS = new MachOPlatformRuntimeState();450return MOPS->initialize();451}452453MachOPlatformRuntimeState &MachOPlatformRuntimeState::get() {454assert(MOPS && "MachOPlatformRuntimeState not initialized");455return *MOPS;456}457458Error MachOPlatformRuntimeState::destroy() {459assert(MOPS && "MachOPlatformRuntimeState not initialized");460auto Err = MOPS->shutdown();461delete MOPS;462return Err;463}464465Error MachOPlatformRuntimeState::initialize() {466UseCallbackStyleUnwindInfo = __unw_add_find_dynamic_unwind_sections &&467__unw_remove_find_dynamic_unwind_sections;468if (UseCallbackStyleUnwindInfo) {469ORC_RT_DEBUG({470printdbg("__unw_add/remove_find_dynamic_unwind_sections available."471" Using callback-based frame info lookup.\n");472});473if (__unw_add_find_dynamic_unwind_sections(&findDynamicUnwindSections))474return make_error<StringError>(475"Could not register findDynamicUnwindSections");476} else {477ORC_RT_DEBUG({478printdbg("__unw_add/remove_find_dynamic_unwind_sections not available."479" Using classic frame info registration.\n");480});481}482return Error::success();483}484485Error MachOPlatformRuntimeState::shutdown() {486if (UseCallbackStyleUnwindInfo) {487if (__unw_remove_find_dynamic_unwind_sections(&findDynamicUnwindSections)) {488ORC_RT_DEBUG(489{ printdbg("__unw_remove_find_dynamic_unwind_sections failed.\n"); });490}491}492return Error::success();493}494495Error MachOPlatformRuntimeState::registerJITDylib(std::string Name,496void *Header) {497ORC_RT_DEBUG({498printdbg("Registering JITDylib %s: Header = %p\n", Name.c_str(), Header);499});500std::lock_guard<std::mutex> Lock(JDStatesMutex);501if (JDStates.count(Header)) {502std::ostringstream ErrStream;503ErrStream << "Duplicate JITDylib registration for header " << Header504<< " (name = " << Name << ")";505return make_error<StringError>(ErrStream.str());506}507if (JDNameToHeader.count(Name)) {508std::ostringstream ErrStream;509ErrStream << "Duplicate JITDylib registration for header " << Header510<< " (header = " << Header << ")";511return make_error<StringError>(ErrStream.str());512}513514auto &JDS = JDStates[Header];515JDS.Name = std::move(Name);516JDS.Header = Header;517JDNameToHeader[JDS.Name] = Header;518return Error::success();519}520521Error MachOPlatformRuntimeState::deregisterJITDylib(void *Header) {522std::lock_guard<std::mutex> Lock(JDStatesMutex);523auto I = JDStates.find(Header);524if (I == JDStates.end()) {525std::ostringstream ErrStream;526ErrStream << "Attempted to deregister unrecognized header " << Header;527return make_error<StringError>(ErrStream.str());528}529530// Remove std::string construction once we can use C++20.531auto J = JDNameToHeader.find(532std::string(I->second.Name.data(), I->second.Name.size()));533assert(J != JDNameToHeader.end() &&534"Missing JDNameToHeader entry for JITDylib");535536ORC_RT_DEBUG({537printdbg("Deregistering JITDylib %s: Header = %p\n", I->second.Name.c_str(),538Header);539});540541JDNameToHeader.erase(J);542JDStates.erase(I);543return Error::success();544}545546Error MachOPlatformRuntimeState::registerThreadDataSection(547span<const char> ThreadDataSection) {548std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);549auto I = ThreadDataSections.upper_bound(ThreadDataSection.data());550if (I != ThreadDataSections.begin()) {551auto J = std::prev(I);552if (J->first + J->second > ThreadDataSection.data())553return make_error<StringError>("Overlapping __thread_data sections");554}555ThreadDataSections.insert(556I, std::make_pair(ThreadDataSection.data(), ThreadDataSection.size()));557return Error::success();558}559560Error MachOPlatformRuntimeState::deregisterThreadDataSection(561span<const char> ThreadDataSection) {562std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);563auto I = ThreadDataSections.find(ThreadDataSection.data());564if (I == ThreadDataSections.end())565return make_error<StringError>("Attempt to deregister unknown thread data "566"section");567ThreadDataSections.erase(I);568return Error::success();569}570571Error MachOPlatformRuntimeState::registerObjectSymbolTable(572ExecutorAddr HeaderAddr,573const std::vector<std::tuple<ExecutorAddr, ExecutorAddr,574MachOExecutorSymbolFlags>> &Entries) {575576std::lock_guard<std::mutex> Lock(JDStatesMutex);577auto *JDS = getJITDylibStateByHeader(HeaderAddr.toPtr<void *>());578if (!JDS) {579std::ostringstream ErrStream;580ErrStream << "Could not register object platform sections for "581"unrecognized header "582<< HeaderAddr.toPtr<void *>();583return make_error<StringError>(ErrStream.str());584}585586for (auto &[NameAddr, SymAddr, Flags] : Entries)587JDS->SymbolTable[NameAddr.toPtr<const char *>()] = {SymAddr, Flags};588589return Error::success();590}591592Error MachOPlatformRuntimeState::deregisterObjectSymbolTable(593ExecutorAddr HeaderAddr,594const std::vector<std::tuple<ExecutorAddr, ExecutorAddr,595MachOExecutorSymbolFlags>> &Entries) {596597std::lock_guard<std::mutex> Lock(JDStatesMutex);598auto *JDS = getJITDylibStateByHeader(HeaderAddr.toPtr<void *>());599if (!JDS) {600std::ostringstream ErrStream;601ErrStream << "Could not register object platform sections for "602"unrecognized header "603<< HeaderAddr.toPtr<void *>();604return make_error<StringError>(ErrStream.str());605}606607for (auto &[NameAddr, SymAddr, Flags] : Entries)608JDS->SymbolTable.erase(NameAddr.toPtr<const char *>());609610return Error::success();611}612613Error MachOPlatformRuntimeState::registerObjectPlatformSections(614ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> UnwindInfo,615std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs) {616617// FIXME: Reject platform section registration after the JITDylib is618// sealed?619620ORC_RT_DEBUG({621printdbg("MachOPlatform: Registering object sections for %p.\n",622HeaderAddr.toPtr<void *>());623});624625std::lock_guard<std::mutex> Lock(JDStatesMutex);626auto *JDS = getJITDylibStateByHeader(HeaderAddr.toPtr<void *>());627if (!JDS) {628std::ostringstream ErrStream;629ErrStream << "Could not register object platform sections for "630"unrecognized header "631<< HeaderAddr.toPtr<void *>();632return make_error<StringError>(ErrStream.str());633}634635if (UnwindInfo && UseCallbackStyleUnwindInfo) {636ORC_RT_DEBUG({637printdbg(" Registering new-style unwind info for:\n"638" DWARF: %p -- %p\n"639" Compact-unwind: %p -- %p\n"640" for:\n",641UnwindInfo->DwarfSection.Start.toPtr<void *>(),642UnwindInfo->DwarfSection.End.toPtr<void *>(),643UnwindInfo->CompactUnwindSection.Start.toPtr<void *>(),644UnwindInfo->CompactUnwindSection.End.toPtr<void *>());645});646for (auto &CodeRange : UnwindInfo->CodeRanges) {647JDS->UnwindSections.insert(CodeRange.Start.toPtr<char *>(),648CodeRange.End.toPtr<char *>(), *UnwindInfo);649ORC_RT_DEBUG({650printdbg(" [ %p -- %p ]\n", CodeRange.Start.toPtr<void *>(),651CodeRange.End.toPtr<void *>());652});653}654}655656for (auto &KV : Secs) {657// FIXME: Validate section ranges?658if (KV.first == "__TEXT,__eh_frame") {659if (!UseCallbackStyleUnwindInfo) {660// Use classic libunwind registration.661if (auto Err = registerEHFrames(KV.second.toSpan<const char>()))662return Err;663}664} else if (KV.first == "__DATA,__data") {665assert(!JDS->DataSectionContent.count(KV.second.Start.toPtr<char *>()) &&666"Address already registered.");667auto S = KV.second.toSpan<char>();668JDS->DataSectionContent[KV.second.Start.toPtr<char *>()] =669std::vector<char>(S.begin(), S.end());670} else if (KV.first == "__DATA,__common") {671JDS->ZeroInitRanges[KV.second.Start.toPtr<char *>()] = KV.second.size();672} else if (KV.first == "__DATA,__thread_data") {673if (auto Err = registerThreadDataSection(KV.second.toSpan<const char>()))674return Err;675} else if (KV.first == "__llvm_jitlink_ObjCRuntimeRegistrationObject")676JDS->ObjCRuntimeRegistrationObjects.add(KV.second.toSpan<char>());677else if (KV.first == "__DATA,__mod_init_func")678JDS->ModInitsSections.add(KV.second.toSpan<void (*)()>());679else {680// Should this be a warning instead?681return make_error<StringError>(682"Encountered unexpected section " +683std::string(KV.first.data(), KV.first.size()) +684" while registering object platform sections");685}686}687688return Error::success();689}690691Error MachOPlatformRuntimeState::deregisterObjectPlatformSections(692ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> UnwindInfo,693std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs) {694// TODO: Make this more efficient? (maybe unnecessary if removal is rare?)695// TODO: Add a JITDylib prepare-for-teardown operation that clears all696// registered sections, causing this function to take the fast-path.697ORC_RT_DEBUG({698printdbg("MachOPlatform: Deregistering object sections for %p.\n",699HeaderAddr.toPtr<void *>());700});701702std::lock_guard<std::mutex> Lock(JDStatesMutex);703auto *JDS = getJITDylibStateByHeader(HeaderAddr.toPtr<void *>());704if (!JDS) {705std::ostringstream ErrStream;706ErrStream << "Could not register object platform sections for unrecognized "707"header "708<< HeaderAddr.toPtr<void *>();709return make_error<StringError>(ErrStream.str());710}711712// FIXME: Implement faster-path by returning immediately if JDS is being713// torn down entirely?714715// TODO: Make library permanent (i.e. not able to be dlclosed) if it contains716// any Swift or ObjC. Once this happens we can clear (and no longer record)717// data section content, as the library could never be re-initialized.718719if (UnwindInfo && UseCallbackStyleUnwindInfo) {720ORC_RT_DEBUG({721printdbg(" Deregistering new-style unwind info for:\n"722" DWARF: %p -- %p\n"723" Compact-unwind: %p -- %p\n"724" for:\n",725UnwindInfo->DwarfSection.Start.toPtr<void *>(),726UnwindInfo->DwarfSection.End.toPtr<void *>(),727UnwindInfo->CompactUnwindSection.Start.toPtr<void *>(),728UnwindInfo->CompactUnwindSection.End.toPtr<void *>());729});730for (auto &CodeRange : UnwindInfo->CodeRanges) {731JDS->UnwindSections.erase(CodeRange.Start.toPtr<char *>(),732CodeRange.End.toPtr<char *>());733ORC_RT_DEBUG({734printdbg(" [ %p -- %p ]\n", CodeRange.Start.toPtr<void *>(),735CodeRange.End.toPtr<void *>());736});737}738}739740for (auto &KV : Secs) {741// FIXME: Validate section ranges?742if (KV.first == "__TEXT,__eh_frame") {743if (!UseCallbackStyleUnwindInfo) {744// Use classic libunwind registration.745if (auto Err = deregisterEHFrames(KV.second.toSpan<const char>()))746return Err;747}748} else if (KV.first == "__DATA,__data") {749JDS->DataSectionContent.erase(KV.second.Start.toPtr<char *>());750} else if (KV.first == "__DATA,__common") {751JDS->ZeroInitRanges.erase(KV.second.Start.toPtr<char *>());752} else if (KV.first == "__DATA,__thread_data") {753if (auto Err =754deregisterThreadDataSection(KV.second.toSpan<const char>()))755return Err;756} else if (KV.first == "__llvm_jitlink_ObjCRuntimeRegistrationObject")757JDS->ObjCRuntimeRegistrationObjects.removeIfPresent(KV.second);758else if (KV.first == "__DATA,__mod_init_func")759JDS->ModInitsSections.removeIfPresent(KV.second);760else {761// Should this be a warning instead?762return make_error<StringError>(763"Encountered unexpected section " +764std::string(KV.first.data(), KV.first.size()) +765" while deregistering object platform sections");766}767}768return Error::success();769}770771const char *MachOPlatformRuntimeState::dlerror() { return DLFcnError.c_str(); }772773void *MachOPlatformRuntimeState::dlopen(std::string_view Path, int Mode) {774ORC_RT_DEBUG({775std::string S(Path.data(), Path.size());776printdbg("MachOPlatform::dlopen(\"%s\")\n", S.c_str());777});778std::lock_guard<std::recursive_mutex> Lock(DyldAPIMutex);779if (auto H = dlopenImpl(Path, Mode))780return *H;781else {782// FIXME: Make dlerror thread safe.783DLFcnError = toString(H.takeError());784return nullptr;785}786}787788int MachOPlatformRuntimeState::dlclose(void *DSOHandle) {789ORC_RT_DEBUG({790auto *JDS = getJITDylibStateByHeader(DSOHandle);791std::string DylibName;792if (JDS) {793std::string S;794printdbg("MachOPlatform::dlclose(%p) (%s)\n", DSOHandle, S.c_str());795} else796printdbg("MachOPlatform::dlclose(%p) (%s)\n", DSOHandle,797"invalid handle");798});799std::lock_guard<std::recursive_mutex> Lock(DyldAPIMutex);800if (auto Err = dlcloseImpl(DSOHandle)) {801// FIXME: Make dlerror thread safe.802DLFcnError = toString(std::move(Err));803return -1;804}805return 0;806}807808void *MachOPlatformRuntimeState::dlsym(void *DSOHandle, const char *Symbol) {809std::unique_lock<std::mutex> Lock(JDStatesMutex);810auto *JDS = getJITDylibStateByHeader(DSOHandle);811if (!JDS) {812std::ostringstream ErrStream;813ErrStream << "In call to dlsym, unrecognized header address " << DSOHandle;814DLFcnError = ErrStream.str();815return nullptr;816}817818std::string MangledName = std::string("_") + Symbol;819std::pair<std::string_view, bool> Lookup(MangledName, false);820std::pair<ExecutorAddr, MachOExecutorSymbolFlags> Result;821822if (auto Err = lookupSymbols(*JDS, Lock, {&Result, 1}, {&Lookup, 1})) {823DLFcnError = toString(std::move(Err));824return nullptr;825}826827// Sign callable symbols as functions, to match dyld.828if ((Result.second & MachOExecutorSymbolFlags::Callable) ==829MachOExecutorSymbolFlags::Callable)830return reinterpret_cast<void *>(Result.first.toPtr<void(void)>());831return Result.first.toPtr<void *>();832}833834int MachOPlatformRuntimeState::registerAtExit(void (*F)(void *), void *Arg,835void *DSOHandle) {836// FIXME: Handle out-of-memory errors, returning -1 if OOM.837std::lock_guard<std::mutex> Lock(JDStatesMutex);838auto *JDS = getJITDylibStateByHeader(DSOHandle);839if (!JDS) {840ORC_RT_DEBUG({841printdbg("MachOPlatformRuntimeState::registerAtExit called with "842"unrecognized dso handle %p\n",843DSOHandle);844});845return -1;846}847JDS->AtExits.push_back({F, Arg});848return 0;849}850851void MachOPlatformRuntimeState::runAtExits(852std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) {853auto AtExits = std::move(JDS.AtExits);854855// Unlock while running atexits, as they may trigger operations that modify856// JDStates.857JDStatesLock.unlock();858while (!AtExits.empty()) {859auto &AE = AtExits.back();860AE.Func(AE.Arg);861AtExits.pop_back();862}863JDStatesLock.lock();864}865866void MachOPlatformRuntimeState::runAtExits(void *DSOHandle) {867std::unique_lock<std::mutex> Lock(JDStatesMutex);868auto *JDS = getJITDylibStateByHeader(DSOHandle);869ORC_RT_DEBUG({870printdbg("MachOPlatformRuntimeState::runAtExits called on unrecognized "871"dso_handle %p\n",872DSOHandle);873});874if (JDS)875runAtExits(Lock, *JDS);876}877878Expected<std::pair<const char *, size_t>>879MachOPlatformRuntimeState::getThreadDataSectionFor(const char *ThreadData) {880std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);881auto I = ThreadDataSections.upper_bound(ThreadData);882// Check that we have a valid entry covering this address.883if (I == ThreadDataSections.begin())884return make_error<StringError>("No thread local data section for key");885I = std::prev(I);886if (ThreadData >= I->first + I->second)887return make_error<StringError>("No thread local data section for key");888return *I;889}890891MachOPlatformRuntimeState::JITDylibState *892MachOPlatformRuntimeState::getJITDylibStateByHeader(void *DSOHandle) {893auto I = JDStates.find(DSOHandle);894if (I == JDStates.end()) {895I = JDStates.insert(std::make_pair(DSOHandle, JITDylibState())).first;896I->second.Header = DSOHandle;897}898return &I->second;899}900901MachOPlatformRuntimeState::JITDylibState *902MachOPlatformRuntimeState::getJITDylibStateByName(std::string_view Name) {903// FIXME: Avoid creating string once we have C++20.904auto I = JDNameToHeader.find(std::string(Name.data(), Name.size()));905if (I != JDNameToHeader.end())906return getJITDylibStateByHeader(I->second);907return nullptr;908}909910Error MachOPlatformRuntimeState::requestPushSymbols(911JITDylibState &JDS, span<std::pair<std::string_view, bool>> Symbols) {912Error OpErr = Error::success();913if (auto Err = WrapperFunction<SPSError(914SPSExecutorAddr, SPSSequence<SPSTuple<SPSString, bool>>)>::915call(&__orc_rt_macho_push_symbols_tag, OpErr,916ExecutorAddr::fromPtr(JDS.Header), Symbols)) {917cantFail(std::move(OpErr));918return std::move(Err);919}920return OpErr;921}922923Error MachOPlatformRuntimeState::lookupSymbols(924JITDylibState &JDS, std::unique_lock<std::mutex> &JDStatesLock,925span<std::pair<ExecutorAddr, MachOExecutorSymbolFlags>> Result,926span<std::pair<std::string_view, bool>> Symbols) {927assert(JDStatesLock.owns_lock() &&928"JDStatesLock should be locked at call-site");929assert(Result.size() == Symbols.size() &&930"Results and Symbols span sizes should match");931932// Make an initial pass over the local symbol table.933std::vector<size_t> MissingSymbolIndexes;934for (size_t Idx = 0; Idx != Symbols.size(); ++Idx) {935auto I = JDS.SymbolTable.find(Symbols[Idx].first);936if (I != JDS.SymbolTable.end())937Result[Idx] = I->second;938else939MissingSymbolIndexes.push_back(Idx);940}941942// If everything has been resolved already then bail out early.943if (MissingSymbolIndexes.empty())944return Error::success();945946// Otherwise call back to the controller to try to request that the symbol947// be materialized.948std::vector<std::pair<std::string_view, bool>> MissingSymbols;949MissingSymbols.reserve(MissingSymbolIndexes.size());950ORC_RT_DEBUG({951printdbg("requesting push of %i missing symbols...\n",952MissingSymbolIndexes.size());953});954for (auto MissingIdx : MissingSymbolIndexes)955MissingSymbols.push_back(Symbols[MissingIdx]);956957JDStatesLock.unlock();958if (auto Err = requestPushSymbols(959JDS, {MissingSymbols.data(), MissingSymbols.size()}))960return Err;961JDStatesLock.lock();962963// Try to resolve the previously missing symbols locally.964std::vector<size_t> MissingRequiredSymbols;965for (auto MissingIdx : MissingSymbolIndexes) {966auto I = JDS.SymbolTable.find(Symbols[MissingIdx].first);967if (I != JDS.SymbolTable.end())968Result[MissingIdx] = I->second;969else {970if (Symbols[MissingIdx].second)971MissingRequiredSymbols.push_back(MissingIdx);972else973Result[MissingIdx] = {ExecutorAddr(), {}};974}975}976977// Error out if any missing symbols could not be resolved.978if (!MissingRequiredSymbols.empty()) {979std::ostringstream ErrStream;980ErrStream << "Lookup could not find required symbols: [ ";981for (auto MissingIdx : MissingRequiredSymbols)982ErrStream << "\"" << Symbols[MissingIdx].first << "\" ";983ErrStream << "]";984return make_error<StringError>(ErrStream.str());985}986987return Error::success();988}989990// eh-frame registration functions.991// We expect these to be available for all processes.992extern "C" void __register_frame(const void *);993extern "C" void __deregister_frame(const void *);994995template <typename HandleFDEFn>996void walkEHFrameSection(span<const char> EHFrameSection,997HandleFDEFn HandleFDE) {998const char *CurCFIRecord = EHFrameSection.data();999uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);10001001while (CurCFIRecord != EHFrameSection.end() && Size != 0) {1002const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);1003if (Size == 0xffffffff)1004Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;1005else1006Size += 4;1007uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);10081009if (Offset != 0)1010HandleFDE(CurCFIRecord);10111012CurCFIRecord += Size;1013Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);1014}1015}10161017bool MachOPlatformRuntimeState::lookupUnwindSections(1018void *Addr, unw_dynamic_unwind_sections &Info) {1019ORC_RT_DEBUG(1020{ printdbg("Tried to lookup unwind-info via new lookup call.\n"); });1021std::lock_guard<std::mutex> Lock(JDStatesMutex);1022for (auto &KV : JDStates) {1023auto &JD = KV.second;1024auto I = JD.UnwindSections.find(reinterpret_cast<char *>(Addr));1025if (I != JD.UnwindSections.end()) {1026Info.dso_base = reinterpret_cast<uintptr_t>(JD.Header);1027Info.dwarf_section =1028reinterpret_cast<uintptr_t>(I->second.DwarfSection.data());1029Info.dwarf_section_length = I->second.DwarfSection.size();1030Info.compact_unwind_section =1031reinterpret_cast<uintptr_t>(I->second.CompactUnwindSection.data());1032Info.compact_unwind_section_length =1033I->second.CompactUnwindSection.size();1034return true;1035}1036}1037return false;1038}10391040int MachOPlatformRuntimeState::findDynamicUnwindSections(1041uintptr_t addr, unw_dynamic_unwind_sections *info) {1042if (!info)1043return 0;1044return MachOPlatformRuntimeState::get().lookupUnwindSections((void *)addr,1045*info);1046}10471048Error MachOPlatformRuntimeState::registerEHFrames(1049span<const char> EHFrameSection) {1050walkEHFrameSection(EHFrameSection, __register_frame);1051return Error::success();1052}10531054Error MachOPlatformRuntimeState::deregisterEHFrames(1055span<const char> EHFrameSection) {1056walkEHFrameSection(EHFrameSection, __deregister_frame);1057return Error::success();1058}10591060Error MachOPlatformRuntimeState::registerObjCRegistrationObjects(1061JITDylibState &JDS) {1062ORC_RT_DEBUG(printdbg("Registering Objective-C / Swift metadata.\n"));10631064std::vector<char *> RegObjBases;1065JDS.ObjCRuntimeRegistrationObjects.processNewSections(1066[&](span<char> RegObj) { RegObjBases.push_back(RegObj.data()); });10671068if (RegObjBases.empty())1069return Error::success();10701071if (!_objc_map_images || !_objc_load_image)1072return make_error<StringError>(1073"Could not register Objective-C / Swift metadata: _objc_map_images / "1074"_objc_load_image not found");10751076std::vector<char *> Paths;1077Paths.resize(RegObjBases.size());1078_objc_map_images(RegObjBases.size(), Paths.data(),1079reinterpret_cast<mach_header **>(RegObjBases.data()));10801081for (void *RegObjBase : RegObjBases)1082_objc_load_image(nullptr, reinterpret_cast<mach_header *>(RegObjBase));10831084return Error::success();1085}10861087Error MachOPlatformRuntimeState::runModInits(1088std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) {1089std::vector<span<void (*)()>> InitSections;1090InitSections.reserve(JDS.ModInitsSections.numNewSections());10911092// Copy initializer sections: If the JITDylib is unsealed then the1093// initializers could reach back into the JIT and cause more initializers to1094// be added.1095// FIXME: Skip unlock and run in-place on sealed JITDylibs?1096JDS.ModInitsSections.processNewSections(1097[&](span<void (*)()> Inits) { InitSections.push_back(Inits); });10981099JDStatesLock.unlock();1100for (auto InitSec : InitSections)1101for (auto *Init : InitSec)1102Init();1103JDStatesLock.lock();11041105return Error::success();1106}11071108Expected<void *> MachOPlatformRuntimeState::dlopenImpl(std::string_view Path,1109int Mode) {1110std::unique_lock<std::mutex> Lock(JDStatesMutex);11111112// Try to find JITDylib state by name.1113auto *JDS = getJITDylibStateByName(Path);11141115if (!JDS)1116return make_error<StringError>("No registered JTIDylib for path " +1117std::string(Path.data(), Path.size()));11181119// If this JITDylib is unsealed, or this is the first dlopen then run1120// full dlopen path (update deps, push and run initializers, update ref1121// counts on all JITDylibs in the dep tree).1122if (!JDS->referenced() || !JDS->Sealed) {1123if (auto Err = dlopenFull(Lock, *JDS))1124return std::move(Err);1125}11261127// Bump the ref-count on this dylib.1128++JDS->DlRefCount;11291130// Return the header address.1131return JDS->Header;1132}11331134Error MachOPlatformRuntimeState::dlopenFull(1135std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) {1136// Call back to the JIT to push the initializers.1137Expected<MachOJITDylibDepInfoMap> DepInfo((MachOJITDylibDepInfoMap()));1138// Unlock so that we can accept the initializer update.1139JDStatesLock.unlock();1140if (auto Err = WrapperFunction<SPSExpected<SPSMachOJITDylibDepInfoMap>(1141SPSExecutorAddr)>::call(&__orc_rt_macho_push_initializers_tag,1142DepInfo, ExecutorAddr::fromPtr(JDS.Header)))1143return Err;1144JDStatesLock.lock();11451146if (!DepInfo)1147return DepInfo.takeError();11481149if (auto Err = dlopenInitialize(JDStatesLock, JDS, *DepInfo))1150return Err;11511152if (!DepInfo->empty()) {1153ORC_RT_DEBUG({1154printdbg("Unrecognized dep-info key headers in dlopen of %s\n",1155JDS.Name.c_str());1156});1157std::ostringstream ErrStream;1158ErrStream << "Encountered unrecognized dep-info key headers "1159"while processing dlopen of "1160<< JDS.Name;1161return make_error<StringError>(ErrStream.str());1162}11631164return Error::success();1165}11661167Error MachOPlatformRuntimeState::dlopenInitialize(1168std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS,1169MachOJITDylibDepInfoMap &DepInfo) {1170ORC_RT_DEBUG({1171printdbg("MachOPlatformRuntimeState::dlopenInitialize(\"%s\")\n",1172JDS.Name.c_str());1173});11741175// If the header is not present in the dep map then assume that we1176// already processed it earlier in the dlopenInitialize traversal and1177// return.1178// TODO: Keep a visited set instead so that we can error out on missing1179// entries?1180auto I = DepInfo.find(ExecutorAddr::fromPtr(JDS.Header));1181if (I == DepInfo.end())1182return Error::success();11831184auto DI = std::move(I->second);1185DepInfo.erase(I);11861187// We don't need to re-initialize sealed JITDylibs that have already been1188// initialized. Just check that their dep-map entry is empty as expected.1189if (JDS.Sealed) {1190if (!DI.DepHeaders.empty()) {1191std::ostringstream ErrStream;1192ErrStream << "Sealed JITDylib " << JDS.Header1193<< " already has registered dependencies";1194return make_error<StringError>(ErrStream.str());1195}1196if (JDS.referenced())1197return Error::success();1198} else1199JDS.Sealed = DI.Sealed;12001201// This is an unsealed or newly sealed JITDylib. Run initializers.1202std::vector<JITDylibState *> OldDeps;1203std::swap(JDS.Deps, OldDeps);1204JDS.Deps.reserve(DI.DepHeaders.size());1205for (auto DepHeaderAddr : DI.DepHeaders) {1206auto *DepJDS = getJITDylibStateByHeader(DepHeaderAddr.toPtr<void *>());1207if (!DepJDS) {1208std::ostringstream ErrStream;1209ErrStream << "Encountered unrecognized dep header "1210<< DepHeaderAddr.toPtr<void *>() << " while initializing "1211<< JDS.Name;1212return make_error<StringError>(ErrStream.str());1213}1214++DepJDS->LinkedAgainstRefCount;1215if (auto Err = dlopenInitialize(JDStatesLock, *DepJDS, DepInfo))1216return Err;1217}12181219// Initialize this JITDylib.1220if (auto Err = registerObjCRegistrationObjects(JDS))1221return Err;1222if (auto Err = runModInits(JDStatesLock, JDS))1223return Err;12241225// Decrement old deps.1226// FIXME: We should probably continue and just report deinitialize errors1227// here.1228for (auto *DepJDS : OldDeps) {1229--DepJDS->LinkedAgainstRefCount;1230if (!DepJDS->referenced())1231if (auto Err = dlcloseDeinitialize(JDStatesLock, *DepJDS))1232return Err;1233}12341235return Error::success();1236}12371238Error MachOPlatformRuntimeState::dlcloseImpl(void *DSOHandle) {1239std::unique_lock<std::mutex> Lock(JDStatesMutex);12401241// Try to find JITDylib state by header.1242auto *JDS = getJITDylibStateByHeader(DSOHandle);12431244if (!JDS) {1245std::ostringstream ErrStream;1246ErrStream << "No registered JITDylib for " << DSOHandle;1247return make_error<StringError>(ErrStream.str());1248}12491250// Bump the ref-count.1251--JDS->DlRefCount;12521253if (!JDS->referenced())1254return dlcloseDeinitialize(Lock, *JDS);12551256return Error::success();1257}12581259Error MachOPlatformRuntimeState::dlcloseDeinitialize(1260std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) {12611262ORC_RT_DEBUG({1263printdbg("MachOPlatformRuntimeState::dlcloseDeinitialize(\"%s\")\n",1264JDS.Name.c_str());1265});12661267runAtExits(JDStatesLock, JDS);12681269// Reset mod-inits1270JDS.ModInitsSections.reset();12711272// Reset data section contents.1273for (auto &KV : JDS.DataSectionContent)1274memcpy(KV.first, KV.second.data(), KV.second.size());1275for (auto &KV : JDS.ZeroInitRanges)1276memset(KV.first, 0, KV.second);12771278// Deinitialize any dependencies.1279for (auto *DepJDS : JDS.Deps) {1280--DepJDS->LinkedAgainstRefCount;1281if (!DepJDS->referenced())1282if (auto Err = dlcloseDeinitialize(JDStatesLock, *DepJDS))1283return Err;1284}12851286return Error::success();1287}12881289class MachOPlatformRuntimeTLVManager {1290public:1291void *getInstance(const char *ThreadData);12921293private:1294std::unordered_map<const char *, char *> Instances;1295std::unordered_map<const char *, std::unique_ptr<char[]>> AllocatedSections;1296};12971298void *MachOPlatformRuntimeTLVManager::getInstance(const char *ThreadData) {1299auto I = Instances.find(ThreadData);1300if (I != Instances.end())1301return I->second;13021303auto TDS =1304MachOPlatformRuntimeState::get().getThreadDataSectionFor(ThreadData);1305if (!TDS) {1306__orc_rt_log_error(toString(TDS.takeError()).c_str());1307return nullptr;1308}13091310auto &Allocated = AllocatedSections[TDS->first];1311if (!Allocated) {1312Allocated = std::make_unique<char[]>(TDS->second);1313memcpy(Allocated.get(), TDS->first, TDS->second);1314}13151316size_t ThreadDataDelta = ThreadData - TDS->first;1317assert(ThreadDataDelta <= TDS->second && "ThreadData outside section bounds");13181319char *Instance = Allocated.get() + ThreadDataDelta;1320Instances[ThreadData] = Instance;1321return Instance;1322}13231324void destroyMachOTLVMgr(void *MachOTLVMgr) {1325delete static_cast<MachOPlatformRuntimeTLVManager *>(MachOTLVMgr);1326}13271328Error runWrapperFunctionCalls(std::vector<WrapperFunctionCall> WFCs) {1329for (auto &WFC : WFCs)1330if (auto Err = WFC.runWithSPSRet<void>())1331return Err;1332return Error::success();1333}13341335} // end anonymous namespace13361337//------------------------------------------------------------------------------1338// JIT entry points1339//------------------------------------------------------------------------------13401341ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult1342__orc_rt_macho_platform_bootstrap(char *ArgData, size_t ArgSize) {1343return WrapperFunction<SPSError()>::handle(1344ArgData, ArgSize,1345[]() { return MachOPlatformRuntimeState::create(); })1346.release();1347}13481349ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult1350__orc_rt_macho_platform_shutdown(char *ArgData, size_t ArgSize) {1351return WrapperFunction<SPSError()>::handle(1352ArgData, ArgSize,1353[]() { return MachOPlatformRuntimeState::destroy(); })1354.release();1355}13561357ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult1358__orc_rt_macho_register_jitdylib(char *ArgData, size_t ArgSize) {1359return WrapperFunction<SPSError(SPSString, SPSExecutorAddr)>::handle(1360ArgData, ArgSize,1361[](std::string &Name, ExecutorAddr HeaderAddr) {1362return MachOPlatformRuntimeState::get().registerJITDylib(1363std::move(Name), HeaderAddr.toPtr<void *>());1364})1365.release();1366}13671368ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult1369__orc_rt_macho_deregister_jitdylib(char *ArgData, size_t ArgSize) {1370return WrapperFunction<SPSError(SPSExecutorAddr)>::handle(1371ArgData, ArgSize,1372[](ExecutorAddr HeaderAddr) {1373return MachOPlatformRuntimeState::get().deregisterJITDylib(1374HeaderAddr.toPtr<void *>());1375})1376.release();1377}13781379ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult1380__orc_rt_macho_register_object_platform_sections(char *ArgData,1381size_t ArgSize) {1382return WrapperFunction<SPSError(SPSExecutorAddr,1383SPSOptional<SPSUnwindSectionInfo>,1384SPSMachOObjectPlatformSectionsMap)>::1385handle(ArgData, ArgSize,1386[](ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> USI,1387std::vector<std::pair<std::string_view, ExecutorAddrRange>>1388&Secs) {1389return MachOPlatformRuntimeState::get()1390.registerObjectPlatformSections(HeaderAddr, std::move(USI),1391std::move(Secs));1392})1393.release();1394}13951396ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult1397__orc_rt_macho_register_object_symbol_table(char *ArgData, size_t ArgSize) {1398using SymtabContainer = std::vector<1399std::tuple<ExecutorAddr, ExecutorAddr,1400MachOPlatformRuntimeState::MachOExecutorSymbolFlags>>;1401return WrapperFunction<SPSError(1402SPSExecutorAddr, SPSSequence<SPSTuple<SPSExecutorAddr, SPSExecutorAddr,1403SPSMachOExecutorSymbolFlags>>)>::1404handle(ArgData, ArgSize,1405[](ExecutorAddr HeaderAddr, SymtabContainer &Symbols) {1406return MachOPlatformRuntimeState::get()1407.registerObjectSymbolTable(HeaderAddr, Symbols);1408})1409.release();1410}14111412ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult1413__orc_rt_macho_deregister_object_symbol_table(char *ArgData, size_t ArgSize) {1414using SymtabContainer = std::vector<1415std::tuple<ExecutorAddr, ExecutorAddr,1416MachOPlatformRuntimeState::MachOExecutorSymbolFlags>>;1417return WrapperFunction<SPSError(1418SPSExecutorAddr, SPSSequence<SPSTuple<SPSExecutorAddr, SPSExecutorAddr,1419SPSMachOExecutorSymbolFlags>>)>::1420handle(ArgData, ArgSize,1421[](ExecutorAddr HeaderAddr, SymtabContainer &Symbols) {1422return MachOPlatformRuntimeState::get()1423.deregisterObjectSymbolTable(HeaderAddr, Symbols);1424})1425.release();1426}14271428ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult1429__orc_rt_macho_deregister_object_platform_sections(char *ArgData,1430size_t ArgSize) {1431return WrapperFunction<SPSError(SPSExecutorAddr,1432SPSOptional<SPSUnwindSectionInfo>,1433SPSMachOObjectPlatformSectionsMap)>::1434handle(ArgData, ArgSize,1435[](ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> USI,1436std::vector<std::pair<std::string_view, ExecutorAddrRange>>1437&Secs) {1438return MachOPlatformRuntimeState::get()1439.deregisterObjectPlatformSections(HeaderAddr, std::move(USI),1440std::move(Secs));1441})1442.release();1443}14441445ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult1446__orc_rt_macho_run_wrapper_function_calls(char *ArgData, size_t ArgSize) {1447return WrapperFunction<SPSError(SPSSequence<SPSWrapperFunctionCall>)>::handle(1448ArgData, ArgSize, runWrapperFunctionCalls)1449.release();1450}14511452//------------------------------------------------------------------------------1453// TLV support1454//------------------------------------------------------------------------------14551456ORC_RT_INTERFACE void *__orc_rt_macho_tlv_get_addr_impl(TLVDescriptor *D) {1457auto *TLVMgr = static_cast<MachOPlatformRuntimeTLVManager *>(1458pthread_getspecific(D->Key));1459if (!TLVMgr) {1460TLVMgr = new MachOPlatformRuntimeTLVManager();1461if (pthread_setspecific(D->Key, TLVMgr)) {1462__orc_rt_log_error("Call to pthread_setspecific failed");1463return nullptr;1464}1465}14661467return TLVMgr->getInstance(1468reinterpret_cast<char *>(static_cast<uintptr_t>(D->DataAddress)));1469}14701471ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult1472__orc_rt_macho_create_pthread_key(char *ArgData, size_t ArgSize) {1473return WrapperFunction<SPSExpected<uint64_t>(void)>::handle(1474ArgData, ArgSize,1475[]() -> Expected<uint64_t> {1476pthread_key_t Key;1477if (int Err = pthread_key_create(&Key, destroyMachOTLVMgr)) {1478__orc_rt_log_error("Call to pthread_key_create failed");1479return make_error<StringError>(strerror(Err));1480}1481return static_cast<uint64_t>(Key);1482})1483.release();1484}14851486//------------------------------------------------------------------------------1487// cxa_atexit support1488//------------------------------------------------------------------------------14891490int __orc_rt_macho_cxa_atexit(void (*func)(void *), void *arg,1491void *dso_handle) {1492return MachOPlatformRuntimeState::get().registerAtExit(func, arg, dso_handle);1493}14941495void __orc_rt_macho_cxa_finalize(void *dso_handle) {1496MachOPlatformRuntimeState::get().runAtExits(dso_handle);1497}14981499//------------------------------------------------------------------------------1500// JIT'd dlfcn alternatives.1501//------------------------------------------------------------------------------15021503const char *__orc_rt_macho_jit_dlerror() {1504return MachOPlatformRuntimeState::get().dlerror();1505}15061507void *__orc_rt_macho_jit_dlopen(const char *path, int mode) {1508return MachOPlatformRuntimeState::get().dlopen(path, mode);1509}15101511int __orc_rt_macho_jit_dlclose(void *dso_handle) {1512return MachOPlatformRuntimeState::get().dlclose(dso_handle);1513}15141515void *__orc_rt_macho_jit_dlsym(void *dso_handle, const char *symbol) {1516return MachOPlatformRuntimeState::get().dlsym(dso_handle, symbol);1517}15181519//------------------------------------------------------------------------------1520// MachO Run Program1521//------------------------------------------------------------------------------15221523ORC_RT_INTERFACE int64_t __orc_rt_macho_run_program(const char *JITDylibName,1524const char *EntrySymbolName,1525int argc, char *argv[]) {1526using MainTy = int (*)(int, char *[]);15271528void *H = __orc_rt_macho_jit_dlopen(JITDylibName,1529__orc_rt::macho::ORC_RT_RTLD_LAZY);1530if (!H) {1531__orc_rt_log_error(__orc_rt_macho_jit_dlerror());1532return -1;1533}15341535auto *Main =1536reinterpret_cast<MainTy>(__orc_rt_macho_jit_dlsym(H, EntrySymbolName));15371538if (!Main) {1539__orc_rt_log_error(__orc_rt_macho_jit_dlerror());1540return -1;1541}15421543int Result = Main(argc, argv);15441545if (__orc_rt_macho_jit_dlclose(H) == -1)1546__orc_rt_log_error(__orc_rt_macho_jit_dlerror());15471548return Result;1549}155015511552