1 //===- coff_platform.cpp --------------------------------------------------===//
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-exception
7 //===----------------------------------------------------------------------===//
9 // This file contains code required to load the rest of the COFF runtime.
11 //===----------------------------------------------------------------------===//
16 #include "coff_platform.h"
20 #include "jit_dispatch.h"
21 #include "wrapper_function_utils.h"
28 #include <string_view>
31 #define DEBUG_TYPE "coff_platform"
33 using namespace orc_rt
;
37 using COFFJITDylibDepInfo
= std::vector
<ExecutorAddr
>;
38 using COFFJITDylibDepInfoMap
=
39 std::unordered_map
<ExecutorAddr
, COFFJITDylibDepInfo
>;
41 using SPSCOFFObjectSectionsMap
=
42 SPSSequence
<SPSTuple
<SPSString
, SPSExecutorAddrRange
>>;
44 using SPSCOFFJITDylibDepInfo
= SPSSequence
<SPSExecutorAddr
>;
46 using SPSCOFFJITDylibDepInfoMap
=
47 SPSSequence
<SPSTuple
<SPSExecutorAddr
, SPSCOFFJITDylibDepInfo
>>;
51 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_coff_symbol_lookup_tag
)
52 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_coff_push_initializers_tag
)
55 class COFFPlatformRuntimeState
{
58 // Manage lists of *tor functions sorted by the last character of subsection
61 void Register(char SubsectionChar
, span
<void (*)(void)> Xtors
) {
62 Subsections
[SubsectionChar
- 'A'].push_back(Xtors
);
63 SubsectionsNew
[SubsectionChar
- 'A'].push_back(Xtors
);
66 void RegisterNoRun(char SubsectionChar
, span
<void (*)(void)> Xtors
) {
67 Subsections
[SubsectionChar
- 'A'].push_back(Xtors
);
70 void Reset() { SubsectionsNew
= Subsections
; }
72 void RunAllNewAndFlush();
75 std::array
<std::vector
<span
<void (*)(void)>>, 26> Subsections
;
76 std::array
<std::vector
<span
<void (*)(void)>>, 26> SubsectionsNew
;
79 struct JITDylibState
{
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~XIZ
87 XtorSection CXXInitSection
; // XCA~XCZ
88 XtorSection CPreTermSection
; // XPA~XPZ
89 XtorSection CTermSection
; // XTA~XTZ
91 bool referenced() const {
92 return LinkedAgainstRefCount
!= 0 || DlRefCount
!= 0;
97 static void initialize();
98 static COFFPlatformRuntimeState
&get();
99 static bool isInitialized() { return CPS
; }
100 static void destroy();
102 COFFPlatformRuntimeState() = default;
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;
111 const char *dlerror();
112 void *dlopen(std::string_view Name
, int Mode
);
113 int dlclose(void *Header
);
114 void *dlsym(void *Header
, std::string_view Symbol
);
116 Error
registerJITDylib(std::string Name
, void *Header
);
117 Error
deregisterJITDylib(void *Header
);
119 Error
registerAtExit(ExecutorAddr HeaderAddr
, void (*AtExit
)(void));
121 Error
registerObjectSections(
122 ExecutorAddr HeaderAddr
,
123 std::vector
<std::pair
<std::string_view
, ExecutorAddrRange
>> Secs
,
124 bool RunInitializers
);
125 Error
deregisterObjectSections(
126 ExecutorAddr HeaderAddr
,
127 std::vector
<std::pair
<std::string_view
, ExecutorAddrRange
>> Secs
);
129 void *findJITDylibBaseByPC(uint64_t PC
);
132 Error
registerBlockRange(ExecutorAddr HeaderAddr
, ExecutorAddrRange Range
);
133 Error
deregisterBlockRange(ExecutorAddr HeaderAddr
, ExecutorAddrRange Range
);
135 Error
registerSEHFrames(ExecutorAddr HeaderAddr
,
136 ExecutorAddrRange SEHFrameRange
);
137 Error
deregisterSEHFrames(ExecutorAddr HeaderAddr
,
138 ExecutorAddrRange SEHFrameRange
);
140 Expected
<void *> dlopenImpl(std::string_view Path
, int Mode
);
141 Error
dlopenFull(JITDylibState
&JDS
);
142 Error
dlopenInitialize(JITDylibState
&JDS
, COFFJITDylibDepInfoMap
&DepInfo
);
144 Error
dlcloseImpl(void *DSOHandle
);
145 Error
dlcloseDeinitialize(JITDylibState
&JDS
);
147 JITDylibState
*getJITDylibStateByHeader(void *DSOHandle
);
148 JITDylibState
*getJITDylibStateByName(std::string_view Path
);
149 Expected
<ExecutorAddr
> lookupSymbolInJITDylib(void *DSOHandle
,
150 std::string_view Symbol
);
152 static COFFPlatformRuntimeState
*CPS
;
154 std::recursive_mutex JDStatesMutex
;
155 std::map
<void *, JITDylibState
> JDStates
;
160 std::map
<void *, BlockRange
> BlockRanges
;
161 std::unordered_map
<std::string_view
, void *> JDNameToHeader
;
162 std::string DLFcnError
;
167 COFFPlatformRuntimeState
*COFFPlatformRuntimeState::CPS
= nullptr;
169 COFFPlatformRuntimeState::JITDylibState
*
170 COFFPlatformRuntimeState::getJITDylibStateByHeader(void *Header
) {
171 auto I
= JDStates
.find(Header
);
172 if (I
== JDStates
.end())
177 COFFPlatformRuntimeState::JITDylibState
*
178 COFFPlatformRuntimeState::getJITDylibStateByName(std::string_view Name
) {
179 // FIXME: Avoid creating string copy here.
180 auto I
= JDNameToHeader
.find(std::string(Name
.data(), Name
.size()));
181 if (I
== JDNameToHeader
.end())
184 auto J
= JDStates
.find(H
);
185 assert(J
!= JDStates
.end() &&
186 "JITDylib has name map entry but no header map entry");
190 Error
COFFPlatformRuntimeState::registerJITDylib(std::string Name
,
193 printdbg("Registering JITDylib %s: Header = %p\n", Name
.c_str(), Header
);
195 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
196 if (JDStates
.count(Header
)) {
197 std::ostringstream ErrStream
;
198 ErrStream
<< "Duplicate JITDylib registration for header " << Header
199 << " (name = " << Name
<< ")";
200 return make_error
<StringError
>(ErrStream
.str());
202 if (JDNameToHeader
.count(Name
)) {
203 std::ostringstream ErrStream
;
204 ErrStream
<< "Duplicate JITDylib registration for header " << Header
205 << " (header = " << Header
<< ")";
206 return make_error
<StringError
>(ErrStream
.str());
209 auto &JDS
= JDStates
[Header
];
210 JDS
.Name
= std::move(Name
);
212 JDNameToHeader
[JDS
.Name
] = Header
;
213 return Error::success();
216 Error
COFFPlatformRuntimeState::deregisterJITDylib(void *Header
) {
217 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
218 auto I
= JDStates
.find(Header
);
219 if (I
== JDStates
.end()) {
220 std::ostringstream ErrStream
;
221 ErrStream
<< "Attempted to deregister unrecognized header " << Header
;
222 return make_error
<StringError
>(ErrStream
.str());
225 // Remove std::string construction once we can use C++20.
226 auto J
= JDNameToHeader
.find(
227 std::string(I
->second
.Name
.data(), I
->second
.Name
.size()));
228 assert(J
!= JDNameToHeader
.end() &&
229 "Missing JDNameToHeader entry for JITDylib");
232 printdbg("Deregistering JITDylib %s: Header = %p\n", I
->second
.Name
.c_str(),
236 JDNameToHeader
.erase(J
);
238 return Error::success();
241 void COFFPlatformRuntimeState::XtorSection::RunAllNewAndFlush() {
242 for (auto &Subsection
: SubsectionsNew
) {
243 for (auto &XtorGroup
: Subsection
)
244 for (auto &Xtor
: XtorGroup
)
251 const char *COFFPlatformRuntimeState::dlerror() { return DLFcnError
.c_str(); }
253 void *COFFPlatformRuntimeState::dlopen(std::string_view Path
, int Mode
) {
255 std::string
S(Path
.data(), Path
.size());
256 printdbg("COFFPlatform::dlopen(\"%s\")\n", S
.c_str());
258 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
259 if (auto H
= dlopenImpl(Path
, Mode
))
262 // FIXME: Make dlerror thread safe.
263 DLFcnError
= toString(H
.takeError());
268 int COFFPlatformRuntimeState::dlclose(void *DSOHandle
) {
270 auto *JDS
= getJITDylibStateByHeader(DSOHandle
);
271 std::string DylibName
;
274 printdbg("COFFPlatform::dlclose(%p) (%s)\n", DSOHandle
, S
.c_str());
276 printdbg("COFFPlatform::dlclose(%p) (%s)\n", DSOHandle
, "invalid handle");
278 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
279 if (auto Err
= dlcloseImpl(DSOHandle
)) {
280 // FIXME: Make dlerror thread safe.
281 DLFcnError
= toString(std::move(Err
));
287 void *COFFPlatformRuntimeState::dlsym(void *Header
, std::string_view Symbol
) {
288 auto Addr
= lookupSymbolInJITDylib(Header
, Symbol
);
293 return Addr
->toPtr
<void *>();
296 Expected
<void *> COFFPlatformRuntimeState::dlopenImpl(std::string_view Path
,
298 // Try to find JITDylib state by name.
299 auto *JDS
= getJITDylibStateByName(Path
);
302 return make_error
<StringError
>("No registered JTIDylib for path " +
303 std::string(Path
.data(), Path
.size()));
305 if (auto Err
= dlopenFull(*JDS
))
306 return std::move(Err
);
308 // Bump the ref-count on this dylib.
311 // Return the header address.
315 Error
COFFPlatformRuntimeState::dlopenFull(JITDylibState
&JDS
) {
316 // Call back to the JIT to push the initializers.
317 Expected
<COFFJITDylibDepInfoMap
> DepInfoMap((COFFJITDylibDepInfoMap()));
318 if (auto Err
= WrapperFunction
<SPSExpected
<SPSCOFFJITDylibDepInfoMap
>(
320 call(JITDispatch(&__orc_rt_coff_push_initializers_tag
), DepInfoMap
,
321 ExecutorAddr::fromPtr(JDS
.Header
)))
324 return DepInfoMap
.takeError();
326 if (auto Err
= dlopenInitialize(JDS
, *DepInfoMap
))
329 if (!DepInfoMap
->empty()) {
331 printdbg("Unrecognized dep-info key headers in dlopen of %s\n",
334 std::ostringstream ErrStream
;
335 ErrStream
<< "Encountered unrecognized dep-info key headers "
336 "while processing dlopen of "
338 return make_error
<StringError
>(ErrStream
.str());
341 return Error::success();
344 Error
COFFPlatformRuntimeState::dlopenInitialize(
345 JITDylibState
&JDS
, COFFJITDylibDepInfoMap
&DepInfo
) {
347 printdbg("COFFPlatformRuntimeState::dlopenInitialize(\"%s\")\n",
351 // Skip visited dependency.
352 auto I
= DepInfo
.find(ExecutorAddr::fromPtr(JDS
.Header
));
353 if (I
== DepInfo
.end())
354 return Error::success();
356 auto DI
= std::move(I
->second
);
359 // Run initializers of dependencies in proper order by depth-first traversal
360 // of dependency graph.
361 std::vector
<JITDylibState
*> OldDeps
;
362 std::swap(JDS
.Deps
, OldDeps
);
363 JDS
.Deps
.reserve(DI
.size());
364 for (auto DepHeaderAddr
: DI
) {
365 auto *DepJDS
= getJITDylibStateByHeader(DepHeaderAddr
.toPtr
<void *>());
367 std::ostringstream ErrStream
;
368 ErrStream
<< "Encountered unrecognized dep header "
369 << DepHeaderAddr
.toPtr
<void *>() << " while initializing "
371 return make_error
<StringError
>(ErrStream
.str());
373 ++DepJDS
->LinkedAgainstRefCount
;
374 if (auto Err
= dlopenInitialize(*DepJDS
, DepInfo
))
378 // Run static initializers.
379 JDS
.CInitSection
.RunAllNewAndFlush();
380 JDS
.CXXInitSection
.RunAllNewAndFlush();
382 // Decrement old deps.
383 for (auto *DepJDS
: OldDeps
) {
384 --DepJDS
->LinkedAgainstRefCount
;
385 if (!DepJDS
->referenced())
386 if (auto Err
= dlcloseDeinitialize(*DepJDS
))
390 return Error::success();
393 Error
COFFPlatformRuntimeState::dlcloseImpl(void *DSOHandle
) {
394 // Try to find JITDylib state by header.
395 auto *JDS
= getJITDylibStateByHeader(DSOHandle
);
398 std::ostringstream ErrStream
;
399 ErrStream
<< "No registered JITDylib for " << DSOHandle
;
400 return make_error
<StringError
>(ErrStream
.str());
403 // Bump the ref-count.
406 if (!JDS
->referenced())
407 return dlcloseDeinitialize(*JDS
);
409 return Error::success();
412 Error
COFFPlatformRuntimeState::dlcloseDeinitialize(JITDylibState
&JDS
) {
414 printdbg("COFFPlatformRuntimeState::dlcloseDeinitialize(\"%s\")\n",
419 for (auto AtExit
: JDS
.AtExits
)
423 // Run static terminators.
424 JDS
.CPreTermSection
.RunAllNewAndFlush();
425 JDS
.CTermSection
.RunAllNewAndFlush();
427 // Queue all xtors as new again.
428 JDS
.CInitSection
.Reset();
429 JDS
.CXXInitSection
.Reset();
430 JDS
.CPreTermSection
.Reset();
431 JDS
.CTermSection
.Reset();
433 // Deinitialize any dependencies.
434 for (auto *DepJDS
: JDS
.Deps
) {
435 --DepJDS
->LinkedAgainstRefCount
;
436 if (!DepJDS
->referenced())
437 if (auto Err
= dlcloseDeinitialize(*DepJDS
))
441 return Error::success();
444 Expected
<ExecutorAddr
>
445 COFFPlatformRuntimeState::lookupSymbolInJITDylib(void *header
,
446 std::string_view Sym
) {
447 Expected
<ExecutorAddr
> Result((ExecutorAddr()));
448 if (auto Err
= WrapperFunction
<SPSExpected
<SPSExecutorAddr
>(
450 SPSString
)>::call(JITDispatch(&__orc_rt_coff_symbol_lookup_tag
),
451 Result
, ExecutorAddr::fromPtr(header
), Sym
))
452 return std::move(Err
);
456 Error
COFFPlatformRuntimeState::registerObjectSections(
457 ExecutorAddr HeaderAddr
,
458 std::vector
<std::pair
<std::string_view
, ExecutorAddrRange
>> Secs
,
459 bool RunInitializers
) {
460 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
461 auto I
= JDStates
.find(HeaderAddr
.toPtr
<void *>());
462 if (I
== JDStates
.end()) {
463 std::ostringstream ErrStream
;
464 ErrStream
<< "Unrecognized header " << HeaderAddr
.getValue();
465 return make_error
<StringError
>(ErrStream
.str());
467 auto &JDState
= I
->second
;
468 for (auto &KV
: Secs
) {
469 if (auto Err
= registerBlockRange(HeaderAddr
, KV
.second
))
471 if (KV
.first
.empty())
473 char LastChar
= KV
.first
.data()[KV
.first
.size() - 1];
474 if (KV
.first
== ".pdata") {
475 if (auto Err
= registerSEHFrames(HeaderAddr
, KV
.second
))
477 } else if (KV
.first
>= ".CRT$XIA" && KV
.first
<= ".CRT$XIZ") {
479 JDState
.CInitSection
.Register(LastChar
,
480 KV
.second
.toSpan
<void (*)(void)>());
482 JDState
.CInitSection
.RegisterNoRun(LastChar
,
483 KV
.second
.toSpan
<void (*)(void)>());
484 } else if (KV
.first
>= ".CRT$XCA" && KV
.first
<= ".CRT$XCZ") {
486 JDState
.CXXInitSection
.Register(LastChar
,
487 KV
.second
.toSpan
<void (*)(void)>());
489 JDState
.CXXInitSection
.RegisterNoRun(
490 LastChar
, KV
.second
.toSpan
<void (*)(void)>());
491 } else if (KV
.first
>= ".CRT$XPA" && KV
.first
<= ".CRT$XPZ")
492 JDState
.CPreTermSection
.Register(LastChar
,
493 KV
.second
.toSpan
<void (*)(void)>());
494 else if (KV
.first
>= ".CRT$XTA" && KV
.first
<= ".CRT$XTZ")
495 JDState
.CTermSection
.Register(LastChar
,
496 KV
.second
.toSpan
<void (*)(void)>());
498 return Error::success();
501 Error
COFFPlatformRuntimeState::deregisterObjectSections(
502 ExecutorAddr HeaderAddr
,
503 std::vector
<std::pair
<std::string_view
, ExecutorAddrRange
>> Secs
) {
504 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
505 auto I
= JDStates
.find(HeaderAddr
.toPtr
<void *>());
506 if (I
== JDStates
.end()) {
507 std::ostringstream ErrStream
;
508 ErrStream
<< "Attempted to deregister unrecognized header "
509 << HeaderAddr
.getValue();
510 return make_error
<StringError
>(ErrStream
.str());
512 for (auto &KV
: Secs
) {
513 if (auto Err
= deregisterBlockRange(HeaderAddr
, KV
.second
))
515 if (KV
.first
== ".pdata")
516 if (auto Err
= deregisterSEHFrames(HeaderAddr
, KV
.second
))
519 return Error::success();
522 Error
COFFPlatformRuntimeState::registerSEHFrames(
523 ExecutorAddr HeaderAddr
, ExecutorAddrRange SEHFrameRange
) {
524 int N
= (SEHFrameRange
.End
.getValue() - SEHFrameRange
.Start
.getValue()) /
525 sizeof(RUNTIME_FUNCTION
);
526 auto Func
= SEHFrameRange
.Start
.toPtr
<PRUNTIME_FUNCTION
>();
527 if (!RtlAddFunctionTable(Func
, N
,
528 static_cast<DWORD64
>(HeaderAddr
.getValue())))
529 return make_error
<StringError
>("Failed to register SEH frames");
530 return Error::success();
533 Error
COFFPlatformRuntimeState::deregisterSEHFrames(
534 ExecutorAddr HeaderAddr
, ExecutorAddrRange SEHFrameRange
) {
535 if (!RtlDeleteFunctionTable(SEHFrameRange
.Start
.toPtr
<PRUNTIME_FUNCTION
>()))
536 return make_error
<StringError
>("Failed to deregister SEH frames");
537 return Error::success();
540 Error
COFFPlatformRuntimeState::registerBlockRange(ExecutorAddr HeaderAddr
,
541 ExecutorAddrRange Range
) {
542 assert(!BlockRanges
.count(Range
.Start
.toPtr
<void *>()) &&
543 "Block range address already registered");
544 BlockRange B
= {HeaderAddr
.toPtr
<void *>(), Range
.size()};
545 BlockRanges
.emplace(Range
.Start
.toPtr
<void *>(), B
);
546 return Error::success();
549 Error
COFFPlatformRuntimeState::deregisterBlockRange(ExecutorAddr HeaderAddr
,
550 ExecutorAddrRange Range
) {
551 assert(BlockRanges
.count(Range
.Start
.toPtr
<void *>()) &&
552 "Block range address not registered");
553 BlockRanges
.erase(Range
.Start
.toPtr
<void *>());
554 return Error::success();
557 Error
COFFPlatformRuntimeState::registerAtExit(ExecutorAddr HeaderAddr
,
558 void (*AtExit
)(void)) {
559 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
560 auto I
= JDStates
.find(HeaderAddr
.toPtr
<void *>());
561 if (I
== JDStates
.end()) {
562 std::ostringstream ErrStream
;
563 ErrStream
<< "Unrecognized header " << HeaderAddr
.getValue();
564 return make_error
<StringError
>(ErrStream
.str());
566 I
->second
.AtExits
.push_back(AtExit
);
567 return Error::success();
570 void COFFPlatformRuntimeState::initialize() {
571 assert(!CPS
&& "COFFPlatformRuntimeState should be null");
572 CPS
= new COFFPlatformRuntimeState();
575 COFFPlatformRuntimeState
&COFFPlatformRuntimeState::get() {
576 assert(CPS
&& "COFFPlatformRuntimeState not initialized");
580 void COFFPlatformRuntimeState::destroy() {
581 assert(CPS
&& "COFFPlatformRuntimeState not initialized");
585 void *COFFPlatformRuntimeState::findJITDylibBaseByPC(uint64_t PC
) {
586 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
587 auto It
= BlockRanges
.upper_bound(reinterpret_cast<void *>(PC
));
588 if (It
== BlockRanges
.begin())
591 auto &Range
= It
->second
;
592 if (PC
>= reinterpret_cast<uint64_t>(It
->first
) + Range
.Size
)
597 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
598 __orc_rt_coff_platform_bootstrap(char *ArgData
, size_t ArgSize
) {
599 COFFPlatformRuntimeState::initialize();
600 return WrapperFunctionResult().release();
603 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
604 __orc_rt_coff_platform_shutdown(char *ArgData
, size_t ArgSize
) {
605 COFFPlatformRuntimeState::destroy();
606 return WrapperFunctionResult().release();
609 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
610 __orc_rt_coff_register_jitdylib(char *ArgData
, size_t ArgSize
) {
611 return WrapperFunction
<SPSError(SPSString
, SPSExecutorAddr
)>::handle(
613 [](std::string
&Name
, ExecutorAddr HeaderAddr
) {
614 return COFFPlatformRuntimeState::get().registerJITDylib(
615 std::move(Name
), HeaderAddr
.toPtr
<void *>());
620 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
621 __orc_rt_coff_deregister_jitdylib(char *ArgData
, size_t ArgSize
) {
622 return WrapperFunction
<SPSError(SPSExecutorAddr
)>::handle(
624 [](ExecutorAddr HeaderAddr
) {
625 return COFFPlatformRuntimeState::get().deregisterJITDylib(
626 HeaderAddr
.toPtr
<void *>());
631 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
632 __orc_rt_coff_register_object_sections(char *ArgData
, size_t ArgSize
) {
633 return WrapperFunction
<SPSError(SPSExecutorAddr
, SPSCOFFObjectSectionsMap
,
635 handle(ArgData
, ArgSize
,
636 [](ExecutorAddr HeaderAddr
,
637 std::vector
<std::pair
<std::string_view
, ExecutorAddrRange
>>
639 bool RunInitializers
) {
640 return COFFPlatformRuntimeState::get().registerObjectSections(
641 HeaderAddr
, std::move(Secs
), RunInitializers
);
646 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
647 __orc_rt_coff_deregister_object_sections(char *ArgData
, size_t ArgSize
) {
648 return WrapperFunction
<SPSError(SPSExecutorAddr
, SPSCOFFObjectSectionsMap
)>::
649 handle(ArgData
, ArgSize
,
650 [](ExecutorAddr HeaderAddr
,
651 std::vector
<std::pair
<std::string_view
, ExecutorAddrRange
>>
653 return COFFPlatformRuntimeState::get().deregisterObjectSections(
654 HeaderAddr
, std::move(Secs
));
658 //------------------------------------------------------------------------------
659 // JIT'd dlfcn alternatives.
660 //------------------------------------------------------------------------------
662 const char *__orc_rt_coff_jit_dlerror() {
663 return COFFPlatformRuntimeState::get().dlerror();
666 void *__orc_rt_coff_jit_dlopen(const char *path
, int mode
) {
667 return COFFPlatformRuntimeState::get().dlopen(path
, mode
);
670 int __orc_rt_coff_jit_dlclose(void *header
) {
671 return COFFPlatformRuntimeState::get().dlclose(header
);
674 void *__orc_rt_coff_jit_dlsym(void *header
, const char *symbol
) {
675 return COFFPlatformRuntimeState::get().dlsym(header
, symbol
);
678 //------------------------------------------------------------------------------
679 // COFF SEH exception support
680 //------------------------------------------------------------------------------
687 ORC_RT_INTERFACE
void __stdcall
__orc_rt_coff_cxx_throw_exception(
688 void *pExceptionObject
, ThrowInfo
*pThrowInfo
) {
690 #pragma clang diagnostic push
691 #pragma clang diagnostic ignored "-Wmultichar"
693 constexpr uint32_t EH_EXCEPTION_NUMBER
= 'msc' | 0xE0000000;
695 #pragma clang diagnostic pop
697 constexpr uint32_t EH_MAGIC_NUMBER1
= 0x19930520;
698 auto BaseAddr
= COFFPlatformRuntimeState::get().findJITDylibBaseByPC(
699 reinterpret_cast<uint64_t>(pThrowInfo
));
701 // This is not from JIT'd region.
702 // FIXME: Use the default implementation like below when alias api is
703 // capable. _CxxThrowException(pExceptionObject, pThrowInfo);
704 fprintf(stderr
, "Throwing exception from compiled callback into JIT'd "
705 "exception handler not supported yet.\n");
709 const ULONG_PTR parameters
[] = {
711 reinterpret_cast<ULONG_PTR
>(pExceptionObject
),
712 reinterpret_cast<ULONG_PTR
>(pThrowInfo
),
713 reinterpret_cast<ULONG_PTR
>(BaseAddr
),
715 RaiseException(EH_EXCEPTION_NUMBER
, EXCEPTION_NONCONTINUABLE
,
716 _countof(parameters
), parameters
);
719 //------------------------------------------------------------------------------
721 //------------------------------------------------------------------------------
723 typedef int (*OnExitFunction
)(void);
724 typedef void (*AtExitFunction
)(void);
726 ORC_RT_INTERFACE OnExitFunction
__orc_rt_coff_onexit(void *Header
,
727 OnExitFunction Func
) {
728 if (auto Err
= COFFPlatformRuntimeState::get().registerAtExit(
729 ExecutorAddr::fromPtr(Header
), (void (*)(void))Func
)) {
730 consumeError(std::move(Err
));
736 ORC_RT_INTERFACE
int __orc_rt_coff_atexit(void *Header
, AtExitFunction Func
) {
737 if (auto Err
= COFFPlatformRuntimeState::get().registerAtExit(
738 ExecutorAddr::fromPtr(Header
), (void (*)(void))Func
)) {
739 consumeError(std::move(Err
));
745 //------------------------------------------------------------------------------
747 //------------------------------------------------------------------------------
749 ORC_RT_INTERFACE
int64_t __orc_rt_coff_run_program(const char *JITDylibName
,
750 const char *EntrySymbolName
,
751 int argc
, char *argv
[]) {
752 using MainTy
= int (*)(int, char *[]);
755 __orc_rt_coff_jit_dlopen(JITDylibName
, orc_rt::coff::ORC_RT_RTLD_LAZY
);
757 __orc_rt_log_error(__orc_rt_coff_jit_dlerror());
762 reinterpret_cast<MainTy
>(__orc_rt_coff_jit_dlsym(H
, EntrySymbolName
));
765 __orc_rt_log_error(__orc_rt_coff_jit_dlerror());
769 int Result
= Main(argc
, argv
);
771 if (__orc_rt_coff_jit_dlclose(H
) == -1)
772 __orc_rt_log_error(__orc_rt_coff_jit_dlerror());