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 "wrapper_function_utils.h"
27 #include <string_view>
30 #define DEBUG_TYPE "coff_platform"
32 using namespace __orc_rt
;
36 using COFFJITDylibDepInfo
= std::vector
<ExecutorAddr
>;
37 using COFFJITDylibDepInfoMap
=
38 std::unordered_map
<ExecutorAddr
, COFFJITDylibDepInfo
>;
40 using SPSCOFFObjectSectionsMap
=
41 SPSSequence
<SPSTuple
<SPSString
, SPSExecutorAddrRange
>>;
43 using SPSCOFFJITDylibDepInfo
= SPSSequence
<SPSExecutorAddr
>;
45 using SPSCOFFJITDylibDepInfoMap
=
46 SPSSequence
<SPSTuple
<SPSExecutorAddr
, SPSCOFFJITDylibDepInfo
>>;
48 } // namespace __orc_rt
50 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_coff_symbol_lookup_tag
)
51 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_coff_push_initializers_tag
)
54 class COFFPlatformRuntimeState
{
57 // Manage lists of *tor functions sorted by the last character of subsection
60 void Register(char SubsectionChar
, span
<void (*)(void)> Xtors
) {
61 Subsections
[SubsectionChar
- 'A'].push_back(Xtors
);
62 SubsectionsNew
[SubsectionChar
- 'A'].push_back(Xtors
);
65 void RegisterNoRun(char SubsectionChar
, span
<void (*)(void)> Xtors
) {
66 Subsections
[SubsectionChar
- 'A'].push_back(Xtors
);
69 void Reset() { SubsectionsNew
= Subsections
; }
71 void RunAllNewAndFlush();
74 std::array
<std::vector
<span
<void (*)(void)>>, 26> Subsections
;
75 std::array
<std::vector
<span
<void (*)(void)>>, 26> SubsectionsNew
;
78 struct JITDylibState
{
80 void *Header
= nullptr;
81 size_t LinkedAgainstRefCount
= 0;
82 size_t DlRefCount
= 0;
83 std::vector
<JITDylibState
*> Deps
;
84 std::vector
<void (*)(void)> AtExits
;
85 XtorSection CInitSection
; // XIA~XIZ
86 XtorSection CXXInitSection
; // XCA~XCZ
87 XtorSection CPreTermSection
; // XPA~XPZ
88 XtorSection CTermSection
; // XTA~XTZ
90 bool referenced() const {
91 return LinkedAgainstRefCount
!= 0 || DlRefCount
!= 0;
96 static void initialize();
97 static COFFPlatformRuntimeState
&get();
98 static bool isInitialized() { return CPS
; }
99 static void destroy();
101 COFFPlatformRuntimeState() = default;
103 // Delete copy and move constructors.
104 COFFPlatformRuntimeState(const COFFPlatformRuntimeState
&) = delete;
105 COFFPlatformRuntimeState
&
106 operator=(const COFFPlatformRuntimeState
&) = delete;
107 COFFPlatformRuntimeState(COFFPlatformRuntimeState
&&) = delete;
108 COFFPlatformRuntimeState
&operator=(COFFPlatformRuntimeState
&&) = delete;
110 const char *dlerror();
111 void *dlopen(std::string_view Name
, int Mode
);
112 int dlclose(void *Header
);
113 void *dlsym(void *Header
, std::string_view Symbol
);
115 Error
registerJITDylib(std::string Name
, void *Header
);
116 Error
deregisterJITDylib(void *Header
);
118 Error
registerAtExit(ExecutorAddr HeaderAddr
, void (*AtExit
)(void));
120 Error
registerObjectSections(
121 ExecutorAddr HeaderAddr
,
122 std::vector
<std::pair
<std::string_view
, ExecutorAddrRange
>> Secs
,
123 bool RunInitializers
);
124 Error
deregisterObjectSections(
125 ExecutorAddr HeaderAddr
,
126 std::vector
<std::pair
<std::string_view
, ExecutorAddrRange
>> Secs
);
128 void *findJITDylibBaseByPC(uint64_t PC
);
131 Error
registerBlockRange(ExecutorAddr HeaderAddr
, ExecutorAddrRange Range
);
132 Error
deregisterBlockRange(ExecutorAddr HeaderAddr
, ExecutorAddrRange Range
);
134 Error
registerSEHFrames(ExecutorAddr HeaderAddr
,
135 ExecutorAddrRange SEHFrameRange
);
136 Error
deregisterSEHFrames(ExecutorAddr HeaderAddr
,
137 ExecutorAddrRange SEHFrameRange
);
139 Expected
<void *> dlopenImpl(std::string_view Path
, int Mode
);
140 Error
dlopenFull(JITDylibState
&JDS
);
141 Error
dlopenInitialize(JITDylibState
&JDS
, COFFJITDylibDepInfoMap
&DepInfo
);
143 Error
dlcloseImpl(void *DSOHandle
);
144 Error
dlcloseDeinitialize(JITDylibState
&JDS
);
146 JITDylibState
*getJITDylibStateByHeader(void *DSOHandle
);
147 JITDylibState
*getJITDylibStateByName(std::string_view Path
);
148 Expected
<ExecutorAddr
> lookupSymbolInJITDylib(void *DSOHandle
,
149 std::string_view Symbol
);
151 static COFFPlatformRuntimeState
*CPS
;
153 std::recursive_mutex JDStatesMutex
;
154 std::map
<void *, JITDylibState
> JDStates
;
159 std::map
<void *, BlockRange
> BlockRanges
;
160 std::unordered_map
<std::string_view
, void *> JDNameToHeader
;
161 std::string DLFcnError
;
166 COFFPlatformRuntimeState
*COFFPlatformRuntimeState::CPS
= nullptr;
168 COFFPlatformRuntimeState::JITDylibState
*
169 COFFPlatformRuntimeState::getJITDylibStateByHeader(void *Header
) {
170 auto I
= JDStates
.find(Header
);
171 if (I
== JDStates
.end())
176 COFFPlatformRuntimeState::JITDylibState
*
177 COFFPlatformRuntimeState::getJITDylibStateByName(std::string_view Name
) {
178 // FIXME: Avoid creating string copy here.
179 auto I
= JDNameToHeader
.find(std::string(Name
.data(), Name
.size()));
180 if (I
== JDNameToHeader
.end())
183 auto J
= JDStates
.find(H
);
184 assert(J
!= JDStates
.end() &&
185 "JITDylib has name map entry but no header map entry");
189 Error
COFFPlatformRuntimeState::registerJITDylib(std::string Name
,
192 printdbg("Registering JITDylib %s: Header = %p\n", Name
.c_str(), Header
);
194 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
195 if (JDStates
.count(Header
)) {
196 std::ostringstream ErrStream
;
197 ErrStream
<< "Duplicate JITDylib registration for header " << Header
198 << " (name = " << Name
<< ")";
199 return make_error
<StringError
>(ErrStream
.str());
201 if (JDNameToHeader
.count(Name
)) {
202 std::ostringstream ErrStream
;
203 ErrStream
<< "Duplicate JITDylib registration for header " << Header
204 << " (header = " << Header
<< ")";
205 return make_error
<StringError
>(ErrStream
.str());
208 auto &JDS
= JDStates
[Header
];
209 JDS
.Name
= std::move(Name
);
211 JDNameToHeader
[JDS
.Name
] = Header
;
212 return Error::success();
215 Error
COFFPlatformRuntimeState::deregisterJITDylib(void *Header
) {
216 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
217 auto I
= JDStates
.find(Header
);
218 if (I
== JDStates
.end()) {
219 std::ostringstream ErrStream
;
220 ErrStream
<< "Attempted to deregister unrecognized header " << Header
;
221 return make_error
<StringError
>(ErrStream
.str());
224 // Remove std::string construction once we can use C++20.
225 auto J
= JDNameToHeader
.find(
226 std::string(I
->second
.Name
.data(), I
->second
.Name
.size()));
227 assert(J
!= JDNameToHeader
.end() &&
228 "Missing JDNameToHeader entry for JITDylib");
231 printdbg("Deregistering JITDylib %s: Header = %p\n", I
->second
.Name
.c_str(),
235 JDNameToHeader
.erase(J
);
237 return Error::success();
240 void COFFPlatformRuntimeState::XtorSection::RunAllNewAndFlush() {
241 for (auto &Subsection
: SubsectionsNew
) {
242 for (auto &XtorGroup
: Subsection
)
243 for (auto &Xtor
: XtorGroup
)
250 const char *COFFPlatformRuntimeState::dlerror() { return DLFcnError
.c_str(); }
252 void *COFFPlatformRuntimeState::dlopen(std::string_view Path
, int Mode
) {
254 std::string
S(Path
.data(), Path
.size());
255 printdbg("COFFPlatform::dlopen(\"%s\")\n", S
.c_str());
257 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
258 if (auto H
= dlopenImpl(Path
, Mode
))
261 // FIXME: Make dlerror thread safe.
262 DLFcnError
= toString(H
.takeError());
267 int COFFPlatformRuntimeState::dlclose(void *DSOHandle
) {
269 auto *JDS
= getJITDylibStateByHeader(DSOHandle
);
270 std::string DylibName
;
273 printdbg("COFFPlatform::dlclose(%p) (%s)\n", DSOHandle
, S
.c_str());
275 printdbg("COFFPlatform::dlclose(%p) (%s)\n", DSOHandle
, "invalid handle");
277 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
278 if (auto Err
= dlcloseImpl(DSOHandle
)) {
279 // FIXME: Make dlerror thread safe.
280 DLFcnError
= toString(std::move(Err
));
286 void *COFFPlatformRuntimeState::dlsym(void *Header
, std::string_view Symbol
) {
287 auto Addr
= lookupSymbolInJITDylib(Header
, Symbol
);
292 return Addr
->toPtr
<void *>();
295 Expected
<void *> COFFPlatformRuntimeState::dlopenImpl(std::string_view Path
,
297 // Try to find JITDylib state by name.
298 auto *JDS
= getJITDylibStateByName(Path
);
301 return make_error
<StringError
>("No registered JTIDylib for path " +
302 std::string(Path
.data(), Path
.size()));
304 if (auto Err
= dlopenFull(*JDS
))
305 return std::move(Err
);
307 // Bump the ref-count on this dylib.
310 // Return the header address.
314 Error
COFFPlatformRuntimeState::dlopenFull(JITDylibState
&JDS
) {
315 // Call back to the JIT to push the initializers.
316 Expected
<COFFJITDylibDepInfoMap
> DepInfoMap((COFFJITDylibDepInfoMap()));
317 if (auto Err
= WrapperFunction
<SPSExpected
<SPSCOFFJITDylibDepInfoMap
>(
318 SPSExecutorAddr
)>::call(&__orc_rt_coff_push_initializers_tag
,
320 ExecutorAddr::fromPtr(JDS
.Header
)))
323 return DepInfoMap
.takeError();
325 if (auto Err
= dlopenInitialize(JDS
, *DepInfoMap
))
328 if (!DepInfoMap
->empty()) {
330 printdbg("Unrecognized dep-info key headers in dlopen of %s\n",
333 std::ostringstream ErrStream
;
334 ErrStream
<< "Encountered unrecognized dep-info key headers "
335 "while processing dlopen of "
337 return make_error
<StringError
>(ErrStream
.str());
340 return Error::success();
343 Error
COFFPlatformRuntimeState::dlopenInitialize(
344 JITDylibState
&JDS
, COFFJITDylibDepInfoMap
&DepInfo
) {
346 printdbg("COFFPlatformRuntimeState::dlopenInitialize(\"%s\")\n",
350 // Skip visited dependency.
351 auto I
= DepInfo
.find(ExecutorAddr::fromPtr(JDS
.Header
));
352 if (I
== DepInfo
.end())
353 return Error::success();
355 auto DI
= std::move(I
->second
);
358 // Run initializers of dependencies in proper order by depth-first traversal
359 // of dependency graph.
360 std::vector
<JITDylibState
*> OldDeps
;
361 std::swap(JDS
.Deps
, OldDeps
);
362 JDS
.Deps
.reserve(DI
.size());
363 for (auto DepHeaderAddr
: DI
) {
364 auto *DepJDS
= getJITDylibStateByHeader(DepHeaderAddr
.toPtr
<void *>());
366 std::ostringstream ErrStream
;
367 ErrStream
<< "Encountered unrecognized dep header "
368 << DepHeaderAddr
.toPtr
<void *>() << " while initializing "
370 return make_error
<StringError
>(ErrStream
.str());
372 ++DepJDS
->LinkedAgainstRefCount
;
373 if (auto Err
= dlopenInitialize(*DepJDS
, DepInfo
))
377 // Run static initializers.
378 JDS
.CInitSection
.RunAllNewAndFlush();
379 JDS
.CXXInitSection
.RunAllNewAndFlush();
381 // Decrement old deps.
382 for (auto *DepJDS
: OldDeps
) {
383 --DepJDS
->LinkedAgainstRefCount
;
384 if (!DepJDS
->referenced())
385 if (auto Err
= dlcloseDeinitialize(*DepJDS
))
389 return Error::success();
392 Error
COFFPlatformRuntimeState::dlcloseImpl(void *DSOHandle
) {
393 // Try to find JITDylib state by header.
394 auto *JDS
= getJITDylibStateByHeader(DSOHandle
);
397 std::ostringstream ErrStream
;
398 ErrStream
<< "No registered JITDylib for " << DSOHandle
;
399 return make_error
<StringError
>(ErrStream
.str());
402 // Bump the ref-count.
405 if (!JDS
->referenced())
406 return dlcloseDeinitialize(*JDS
);
408 return Error::success();
411 Error
COFFPlatformRuntimeState::dlcloseDeinitialize(JITDylibState
&JDS
) {
413 printdbg("COFFPlatformRuntimeState::dlcloseDeinitialize(\"%s\")\n",
418 for (auto AtExit
: JDS
.AtExits
)
422 // Run static terminators.
423 JDS
.CPreTermSection
.RunAllNewAndFlush();
424 JDS
.CTermSection
.RunAllNewAndFlush();
426 // Queue all xtors as new again.
427 JDS
.CInitSection
.Reset();
428 JDS
.CXXInitSection
.Reset();
429 JDS
.CPreTermSection
.Reset();
430 JDS
.CTermSection
.Reset();
432 // Deinitialize any dependencies.
433 for (auto *DepJDS
: JDS
.Deps
) {
434 --DepJDS
->LinkedAgainstRefCount
;
435 if (!DepJDS
->referenced())
436 if (auto Err
= dlcloseDeinitialize(*DepJDS
))
440 return Error::success();
443 Expected
<ExecutorAddr
>
444 COFFPlatformRuntimeState::lookupSymbolInJITDylib(void *header
,
445 std::string_view Sym
) {
446 Expected
<ExecutorAddr
> Result((ExecutorAddr()));
447 if (auto Err
= WrapperFunction
<SPSExpected
<SPSExecutorAddr
>(
448 SPSExecutorAddr
, SPSString
)>::call(&__orc_rt_coff_symbol_lookup_tag
,
450 ExecutorAddr::fromPtr(header
),
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 auto &JDState
= I
->second
;
513 for (auto &KV
: Secs
) {
514 if (auto Err
= deregisterBlockRange(HeaderAddr
, KV
.second
))
516 if (KV
.first
== ".pdata")
517 if (auto Err
= deregisterSEHFrames(HeaderAddr
, KV
.second
))
520 return Error::success();
523 Error
COFFPlatformRuntimeState::registerSEHFrames(
524 ExecutorAddr HeaderAddr
, ExecutorAddrRange SEHFrameRange
) {
525 int N
= (SEHFrameRange
.End
.getValue() - SEHFrameRange
.Start
.getValue()) /
526 sizeof(RUNTIME_FUNCTION
);
527 auto Func
= SEHFrameRange
.Start
.toPtr
<PRUNTIME_FUNCTION
>();
528 if (!RtlAddFunctionTable(Func
, N
,
529 static_cast<DWORD64
>(HeaderAddr
.getValue())))
530 return make_error
<StringError
>("Failed to register SEH frames");
531 return Error::success();
534 Error
COFFPlatformRuntimeState::deregisterSEHFrames(
535 ExecutorAddr HeaderAddr
, ExecutorAddrRange SEHFrameRange
) {
536 if (!RtlDeleteFunctionTable(SEHFrameRange
.Start
.toPtr
<PRUNTIME_FUNCTION
>()))
537 return make_error
<StringError
>("Failed to deregister SEH frames");
538 return Error::success();
541 Error
COFFPlatformRuntimeState::registerBlockRange(ExecutorAddr HeaderAddr
,
542 ExecutorAddrRange Range
) {
543 assert(!BlockRanges
.count(Range
.Start
.toPtr
<void *>()) &&
544 "Block range address already registered");
545 BlockRange B
= {HeaderAddr
.toPtr
<void *>(), Range
.size()};
546 BlockRanges
.emplace(Range
.Start
.toPtr
<void *>(), B
);
547 return Error::success();
550 Error
COFFPlatformRuntimeState::deregisterBlockRange(ExecutorAddr HeaderAddr
,
551 ExecutorAddrRange Range
) {
552 assert(BlockRanges
.count(Range
.Start
.toPtr
<void *>()) &&
553 "Block range address not registered");
554 BlockRanges
.erase(Range
.Start
.toPtr
<void *>());
555 return Error::success();
558 Error
COFFPlatformRuntimeState::registerAtExit(ExecutorAddr HeaderAddr
,
559 void (*AtExit
)(void)) {
560 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
561 auto I
= JDStates
.find(HeaderAddr
.toPtr
<void *>());
562 if (I
== JDStates
.end()) {
563 std::ostringstream ErrStream
;
564 ErrStream
<< "Unrecognized header " << HeaderAddr
.getValue();
565 return make_error
<StringError
>(ErrStream
.str());
567 I
->second
.AtExits
.push_back(AtExit
);
568 return Error::success();
571 void COFFPlatformRuntimeState::initialize() {
572 assert(!CPS
&& "COFFPlatformRuntimeState should be null");
573 CPS
= new COFFPlatformRuntimeState();
576 COFFPlatformRuntimeState
&COFFPlatformRuntimeState::get() {
577 assert(CPS
&& "COFFPlatformRuntimeState not initialized");
581 void COFFPlatformRuntimeState::destroy() {
582 assert(CPS
&& "COFFPlatformRuntimeState not initialized");
586 void *COFFPlatformRuntimeState::findJITDylibBaseByPC(uint64_t PC
) {
587 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
588 auto It
= BlockRanges
.upper_bound(reinterpret_cast<void *>(PC
));
589 if (It
== BlockRanges
.begin())
592 auto &Range
= It
->second
;
593 if (PC
>= reinterpret_cast<uint64_t>(It
->first
) + Range
.Size
)
598 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
599 __orc_rt_coff_platform_bootstrap(char *ArgData
, size_t ArgSize
) {
600 COFFPlatformRuntimeState::initialize();
601 return WrapperFunctionResult().release();
604 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
605 __orc_rt_coff_platform_shutdown(char *ArgData
, size_t ArgSize
) {
606 COFFPlatformRuntimeState::destroy();
607 return WrapperFunctionResult().release();
610 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
611 __orc_rt_coff_register_jitdylib(char *ArgData
, size_t ArgSize
) {
612 return WrapperFunction
<SPSError(SPSString
, SPSExecutorAddr
)>::handle(
614 [](std::string
&Name
, ExecutorAddr HeaderAddr
) {
615 return COFFPlatformRuntimeState::get().registerJITDylib(
616 std::move(Name
), HeaderAddr
.toPtr
<void *>());
621 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
622 __orc_rt_coff_deregister_jitdylib(char *ArgData
, size_t ArgSize
) {
623 return WrapperFunction
<SPSError(SPSExecutorAddr
)>::handle(
625 [](ExecutorAddr HeaderAddr
) {
626 return COFFPlatformRuntimeState::get().deregisterJITDylib(
627 HeaderAddr
.toPtr
<void *>());
632 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
633 __orc_rt_coff_register_object_sections(char *ArgData
, size_t ArgSize
) {
634 return WrapperFunction
<SPSError(SPSExecutorAddr
, SPSCOFFObjectSectionsMap
,
636 handle(ArgData
, ArgSize
,
637 [](ExecutorAddr HeaderAddr
,
638 std::vector
<std::pair
<std::string_view
, ExecutorAddrRange
>>
640 bool RunInitializers
) {
641 return COFFPlatformRuntimeState::get().registerObjectSections(
642 HeaderAddr
, std::move(Secs
), RunInitializers
);
647 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
648 __orc_rt_coff_deregister_object_sections(char *ArgData
, size_t ArgSize
) {
649 return WrapperFunction
<SPSError(SPSExecutorAddr
, SPSCOFFObjectSectionsMap
)>::
650 handle(ArgData
, ArgSize
,
651 [](ExecutorAddr HeaderAddr
,
652 std::vector
<std::pair
<std::string_view
, ExecutorAddrRange
>>
654 return COFFPlatformRuntimeState::get().deregisterObjectSections(
655 HeaderAddr
, std::move(Secs
));
659 //------------------------------------------------------------------------------
660 // JIT'd dlfcn alternatives.
661 //------------------------------------------------------------------------------
663 const char *__orc_rt_coff_jit_dlerror() {
664 return COFFPlatformRuntimeState::get().dlerror();
667 void *__orc_rt_coff_jit_dlopen(const char *path
, int mode
) {
668 return COFFPlatformRuntimeState::get().dlopen(path
, mode
);
671 int __orc_rt_coff_jit_dlclose(void *header
) {
672 return COFFPlatformRuntimeState::get().dlclose(header
);
675 void *__orc_rt_coff_jit_dlsym(void *header
, const char *symbol
) {
676 return COFFPlatformRuntimeState::get().dlsym(header
, symbol
);
679 //------------------------------------------------------------------------------
680 // COFF SEH exception support
681 //------------------------------------------------------------------------------
688 ORC_RT_INTERFACE
void __stdcall
__orc_rt_coff_cxx_throw_exception(
689 void *pExceptionObject
, ThrowInfo
*pThrowInfo
) {
690 constexpr uint32_t EH_EXCEPTION_NUMBER
= 'msc' | 0xE0000000;
691 constexpr uint32_t EH_MAGIC_NUMBER1
= 0x19930520;
692 auto BaseAddr
= COFFPlatformRuntimeState::get().findJITDylibBaseByPC(
693 reinterpret_cast<uint64_t>(pThrowInfo
));
695 // This is not from JIT'd region.
696 // FIXME: Use the default implementation like below when alias api is
697 // capable. _CxxThrowException(pExceptionObject, pThrowInfo);
698 fprintf(stderr
, "Throwing exception from compiled callback into JIT'd "
699 "exception handler not supported yet.\n");
703 const ULONG_PTR parameters
[] = {
705 reinterpret_cast<ULONG_PTR
>(pExceptionObject
),
706 reinterpret_cast<ULONG_PTR
>(pThrowInfo
),
707 reinterpret_cast<ULONG_PTR
>(BaseAddr
),
709 RaiseException(EH_EXCEPTION_NUMBER
, EXCEPTION_NONCONTINUABLE
,
710 _countof(parameters
), parameters
);
713 //------------------------------------------------------------------------------
715 //------------------------------------------------------------------------------
717 typedef int (*OnExitFunction
)(void);
718 typedef void (*AtExitFunction
)(void);
720 ORC_RT_INTERFACE OnExitFunction
__orc_rt_coff_onexit(void *Header
,
721 OnExitFunction Func
) {
722 if (auto Err
= COFFPlatformRuntimeState::get().registerAtExit(
723 ExecutorAddr::fromPtr(Header
), (void (*)(void))Func
)) {
724 consumeError(std::move(Err
));
730 ORC_RT_INTERFACE
int __orc_rt_coff_atexit(void *Header
, AtExitFunction Func
) {
731 if (auto Err
= COFFPlatformRuntimeState::get().registerAtExit(
732 ExecutorAddr::fromPtr(Header
), (void (*)(void))Func
)) {
733 consumeError(std::move(Err
));
739 //------------------------------------------------------------------------------
741 //------------------------------------------------------------------------------
743 ORC_RT_INTERFACE
int64_t __orc_rt_coff_run_program(const char *JITDylibName
,
744 const char *EntrySymbolName
,
745 int argc
, char *argv
[]) {
746 using MainTy
= int (*)(int, char *[]);
749 __orc_rt_coff_jit_dlopen(JITDylibName
, __orc_rt::coff::ORC_RT_RTLD_LAZY
);
751 __orc_rt_log_error(__orc_rt_coff_jit_dlerror());
756 reinterpret_cast<MainTy
>(__orc_rt_coff_jit_dlsym(H
, EntrySymbolName
));
759 __orc_rt_log_error(__orc_rt_coff_jit_dlerror());
763 int Result
= Main(argc
, argv
);
765 if (__orc_rt_coff_jit_dlclose(H
) == -1)
766 __orc_rt_log_error(__orc_rt_coff_jit_dlerror());