[PATCH] D108081: [ORC] Add Platform and runtime support for ELF-based platforms
Lang Hames via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 15 04:50:12 PDT 2021
lhames added a comment.
This looks great. Thanks Peter!
I've tested this out in a Linux container and verified that it correctly handles static constructors and destructors in both in-process and out-of-process mode. This is really exciting -- until now only Darwin users have been able to use these features. :)
Please see inline comments -- there are some vestigial TLV functions / members in the ORC runtime, which I think could be removed relatively easily. There are also some in the platform, but they would be tricker to take out -- I would be fine with them staying in in the initial commit.
Side note: This implementation replicates some of MachOPlatform's current warts (e.g. fuzzy operation ordering, JIT-side tracking of init data). This isn't a problem at all, we'll just need to be careful that any fixes made to MachOPlatform are also applied to ELFNix and vice-versa.
I know that you mentioned on discord that you do not have commit access: Would you mind if I removed the walkEHFrame and TLV functions from the runtime, then committed on your behalf?
================
Comment at: compiler-rt/lib/orc/elfnix_platform.cpp:39-59
+template <typename HandleFDEFn>
+void walkEHFrameSection(span<const char> EHFrameSection,
+ HandleFDEFn HandleFDE) {
+ const char *CurCFIRecord = EHFrameSection.data();
+ uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
+
+ while (CurCFIRecord != EHFrameSection.end() && Size != 0) {
----------------
This is kind-of-sort-of out of place, but the situation is complex:
On Darwin the default unwinder is LLVM libunwind, and LLVM libunwind's `__register_frame` and `__deregister_frame` functions expect to be called on individual FDEs.
On Linux the default unwinder is libgcc_s, and libgcc_s's `__register_frame` and `__deregister_frame` functions expect to be called on whole eh-frame //sections//.
In LLVM at the moment we just assume that Darwin implies LLVM libunwind, and anything else implies libgcc_s, but this has also caused problems when people try to use LLVM libunwind on other platforms. See http://llvm.org/PR44074.
I think the best thing to do for now is to stay consistent with the current not-quite-right behavior of LLVM, and assume that ELFNix implies libgcc_s for unwinding: the `walkEHFrameSection` utility should be removed, and `registerObjectSections` and `deregisterObjectSections` should call `__register_frame` and `__deregister_frame` directly on the section ranges.
Separate from this review, we can revisit this as part of http://llvm.org/PR44074 -- I will update that bug with notes and cite this review.
================
Comment at: compiler-rt/lib/orc/elfnix_platform.cpp:164-165
+
+ std::mutex ThreadDataSectionsMutex;
+ std::map<const char *, size_t> ThreadDataSections;
+};
----------------
These are unused and can be removed for now.
================
Comment at: compiler-rt/lib/orc/elfnix_platform.cpp:191-195
+ if (POSR.ThreadDataSection.StartAddress) {
+ if (auto Err = registerThreadDataSection(
+ POSR.ThreadDataSection.toSpan<const char>()))
+ return Err;
+ }
----------------
This can be removed and re-introduced in a future TLV patch.
================
Comment at: compiler-rt/lib/orc/elfnix_platform.cpp:275-286
+Expected<std::pair<const char *, size_t>>
+ELFNixPlatformRuntimeState::getThreadDataSectionFor(const char *ThreadData) {
+ std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);
+ auto I = ThreadDataSections.upper_bound(ThreadData);
+ // Check that we have a valid entry covering this address.
+ if (I == ThreadDataSections.begin())
+ return make_error<StringError>("No thread local data section for key");
----------------
I don't think this is called yet, so the whole function can be removed for now. It can be re-added in future a ELFNix TLV support patch.
================
Comment at: compiler-rt/lib/orc/elfnix_platform.cpp:327-339
+Error ELFNixPlatformRuntimeState::registerThreadDataSection(
+ span<const char> ThreadDataSection) {
+ std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);
+ auto I = ThreadDataSections.upper_bound(ThreadDataSection.data());
+ if (I != ThreadDataSections.begin()) {
+ auto J = std::prev(I);
+ if (J->first + J->second > ThreadDataSection.data())
----------------
This function is only used to put data into currently unused members, so it can be removed for now (and re-added in a future TLV support patch).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D108081/new/
https://reviews.llvm.org/D108081
More information about the llvm-commits
mailing list