diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-18 08:59:49 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-18 08:59:49 +0000 |
| commit | eaabdf5796594be87084758fa524622db1c1dbaa (patch) | |
| tree | 38d0d602accafe5e7145066eb146c993dd162fdb /tools | |
| parent | c5f103663bbee226d20bf6405457a62e7ec41611 (diff) | |
fix(driver): bind MinGW JIT runtime dependencies to host symbols
Resolve the known weak __cxa_pure_virtual reference through the host ABI
instead of JITLink's unsupported absolute-zero fallback. Share the host's
initialized stack guard and failure handler, and map write to _write.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/driver/EmbeddedRunner.cc | 19 | ||||
| -rw-r--r-- | tools/driver/MinGWCOFF.h | 31 |
2 files changed, 47 insertions, 3 deletions
diff --git a/tools/driver/EmbeddedRunner.cc b/tools/driver/EmbeddedRunner.cc index 7bfbcf0..28fe2db 100644 --- a/tools/driver/EmbeddedRunner.cc +++ b/tools/driver/EmbeddedRunner.cc @@ -31,6 +31,9 @@ // Parse all LLVM COFF declarations and helpers before introducing those macros. #include <windows.h> #endif +#ifdef __MINGW32__ +#include <io.h> +#endif namespace { @@ -284,7 +287,7 @@ public: void emit(std::unique_ptr<llvm::orc::MaterializationResponsibility> R, std::unique_ptr<llvm::MemoryBuffer> O) override { - auto Normalized = normalizeMinGWUnwindSections(std::move(O)); + auto Normalized = normalizeMinGWObject(std::move(O)); if (!Normalized) { getExecutionSession().reportError(Normalized.takeError()); R->failMaterialization(); @@ -345,6 +348,12 @@ extern "C" void __cps_jit_noop__main() {} #if defined(__MINGW32__) && defined(__x86_64__) extern "C" void ___chkstk_ms(void); #endif +#ifdef __MINGW32__ +// Use the initialized guard and failure handler from the statically linked +// host runtime rather than loading a second guard and its CRT initializer. +extern "C" uintptr_t __stack_chk_guard; +extern "C" void __stack_chk_fail(void); +#endif static llvm::Error defineRuntimeSymbols(llvm::orc::LLJIT &J) { llvm::orc::SymbolMap Symbols; @@ -370,6 +379,8 @@ static llvm::Error defineRuntimeSymbols(llvm::orc::LLJIT &J) { ExecutorSymbolDef::fromPtr(&__cxxabiv1::__cxa_guard_abort); Symbols[Intern("__cxa_throw")] = ExecutorSymbolDef::fromPtr(&__cxxabiv1::__cxa_throw); + Symbols[Intern("__cxa_pure_virtual")] = + ExecutorSymbolDef::fromPtr(&__cxxabiv1::__cxa_pure_virtual); Symbols[Intern("__cxa_begin_catch")] = ExecutorSymbolDef::fromPtr(&__cxxabiv1::__cxa_begin_catch); Symbols[Intern("__cxa_end_catch")] = @@ -396,6 +407,12 @@ static llvm::Error defineRuntimeSymbols(llvm::orc::LLJIT &J) { ExecutorSymbolDef::fromPtr(&__ms_snprintf); Symbols[Intern("strtoll")] = ExecutorSymbolDef::fromPtr(&std::strtoll); + // msvcrt.dll exports _write; MinGW archive members call its POSIX alias. + Symbols[Intern("write")] = ExecutorSymbolDef::fromPtr(&_write); + Symbols[Intern("__stack_chk_guard")] = + ExecutorSymbolDef::fromPtr(&__stack_chk_guard); + Symbols[Intern("__stack_chk_fail")] = + ExecutorSymbolDef::fromPtr(&__stack_chk_fail); #endif #ifdef _WIN32 // Generated diagnostics write to stderr through __acrt_iob_func(2). The diff --git a/tools/driver/MinGWCOFF.h b/tools/driver/MinGWCOFF.h index 22b8fb2..186d981 100644 --- a/tools/driver/MinGWCOFF.h +++ b/tools/driver/MinGWCOFF.h @@ -6,6 +6,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/Object/COFF.h" #include "llvm/Support/MemoryBuffer.h" +#include <cstddef> #include <cstring> namespace { @@ -20,7 +21,7 @@ inline bool isCOFFUnwindSection(llvm::StringRef Name, llvm::StringRef Base) { // symbol used by relocations. Express their implicit association with .text$foo // as ordinary associative COMDATs in a private copy of the object instead. inline llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> -normalizeMinGWUnwindSections(std::unique_ptr<llvm::MemoryBuffer> Buffer) { +normalizeMinGWObject(std::unique_ptr<llvm::MemoryBuffer> Buffer) { using namespace llvm; auto Object = object::ObjectFile::createObjectFile(Buffer->getMemBufferRef()); if (!Object) @@ -48,8 +49,28 @@ normalizeMinGWUnwindSections(std::unique_ptr<llvm::MemoryBuffer> Buffer) { struct Association { size_t Offset; int32_t Parent; }; SmallVector<Association, 16> Associations; + SmallVector<size_t, 2> PureVirtualReferences; for (const auto &Symbol : COFF->symbols()) { auto Sym = COFF->getCOFFSymbol(Symbol); + if (auto *Weak = Sym.getWeakExternal()) { + auto Name = Symbol.getName(); + if (!Name) + return Name.takeError(); + if (*Name == "__cxa_pure_virtual" && + Weak->Characteristics == COFF::IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY) { + auto Fallback = COFF->getSymbol(Weak->TagIndex); + if (!Fallback) + return Fallback.takeError(); + if (Fallback->isAbsolute() && Fallback->getValue() == 0) { + size_t Offset = reinterpret_cast<const char *>(Sym.getRawPtr()) - + Buffer->getBufferStart(); + Offset += Sym.isBigObj() + ? offsetof(object::coff_symbol32, StorageClass) + : offsetof(object::coff_symbol16, StorageClass); + PureVirtualReferences.push_back(Offset); + } + } + } auto *Def = Sym.getSectionDefinition(); if (!Def || Def->Selection != COFF::IMAGE_COMDAT_SELECT_ANY || Sym.getSectionNumber() <= 0 || @@ -77,7 +98,7 @@ normalizeMinGWUnwindSections(std::unique_ptr<llvm::MemoryBuffer> Buffer) { Buffer->getBufferStart()), Parent->second}); } - if (Associations.empty()) + if (Associations.empty() && PureVirtualReferences.empty()) return std::move(Buffer); auto Copy = WritableMemoryBuffer::getNewUninitMemBuffer( @@ -91,6 +112,12 @@ normalizeMinGWUnwindSections(std::unique_ptr<llvm::MemoryBuffer> Buffer) { Def->NumberLowPart = A.Parent & 0xffff; Def->NumberHighPart = static_cast<uint32_t>(A.Parent) >> 16; } + // JITLink cannot alias a weak external to an absolute-zero fallback. + // The runner always supplies the host's __cxa_pure_virtual, so this known + // optional ABI reference can be an ordinary external. Keep its auxiliary + // entry count intact so the remaining symbol indices do not move. + for (size_t Offset : PureVirtualReferences) + Copy->getBufferStart()[Offset] = COFF::IMAGE_SYM_CLASS_EXTERNAL; return std::unique_ptr<MemoryBuffer>(std::move(Copy)); } |
