jit: instrument COFF add-on load (diagnose Windows exit-127)#2098
Open
jcelerier wants to merge 39 commits into
Open
jit: instrument COFF add-on load (diagnose Windows exit-127)#2098jcelerier wants to merge 39 commits into
jcelerier wants to merge 39 commits into
Conversation
The Windows JIT compiles the add-on but the *load* dies silently (exit 127, no message) -- because the ORC error reporter only appends to m_errors (never prints) and the eager-linking loop consumeError-swallows failures. Make both visible (flushed to stderr) and bracket each load step + per-symbol eager lookup, so the next Windows run shows whether it's a clean JITLink error (and which symbol) or a hard crash, and where. Temporary diagnostic; reverted with the fix.
05caa7e to
1232859
Compare
The instrumented Windows run pinpointed the crash: the JIT link fully succeeds (all add-on symbols resolve) but m_jit->initialize() segfaults (SIGSEGV/139) running static initializers -- and boost.asio thread_locals are among the resolved symbols. Fall back to emulated TLS on COFF (host emutls runtime), keeping native TLS on ELF/MachO, to test whether native COFF TLS is the cause. Also skip llvm.* pseudo-globals (e.g. llvm.global_ctors) in the eager loop.
- Revert the emulated-TLS-on-COFF experiment (it's worse: host has no __emutls_get_address, so the add-on fails to materialize). Back to native TLS. - Add SCORE_JIT_SKIP_INIT env toggle: skip m_jit->initialize() to test whether the Windows crash is purely in running static initializers. - Disable all non-Windows CI on this diag branch and trim win-builds.yaml to the artifact-producing win32 job only, for faster iteration.
A tiny standalone exe (no Qt/score/boost/clang-frontend) that JIT-loads a pre-compiled .ll through the *same* MinGWCOFFPlatform + initialize() path the score JIT uses, so we can isolate the Windows COFF static-init crash with 5-line cases instead of the full generated plugin. Builds in minutes. Cases isolate: trivial / global-ctor / host-call-in-ctor / thread_local-use / tls-in-ctor / exception. The jitmin.yaml workflow builds it against sdk37's LLVM, compiles each case with the SDK clang, and runs jitmin on each -- the step logs pinpoint exactly which construct faults.
c00_trivial (no static init) hard-crashes in initialize() -> the bug is the COFF init dispatch itself, not add-on ctors. Add SKIP_INIT to confirm the JIT otherwise works, run every case (set +e), and log rt_pushInitializers entry to see whether init even reaches our wrapper before crashing.
…ers tail, SendResult)
…OFF dlopen) Root cause (via jitmin): our LLVM-side init dispatch completes cleanly, then orc_rt's COFF dlopen init path segfaults -- it runs .CRT$XC* ctors through the MSVC CRT (_initterm), which a VC-runtime-free MinGW session doesn't provide. Fix: collect each add-on JITDylib's .CRT$XI*/.CRT$XC* ctor addresses at materialization (registerObjectPlatformSections) and run them directly via runAsVoidFunction in a custom MinGWCOFFPlatformSupport::initialize() -- exactly like the bootstrap already does and which we proved works. orc_rt's dlopen init is no longer used on MinGW. (deinitialize is a no-op for now -- teardown dtors are a follow-up.) jitmin reordered to materialize before initialize().
LLJIT's IR layer lowers llvm.global_ctors into a synthetic init function set as the module's init symbol -- no .CRT$XC* section is emitted, so collecting ctor section edges finds nothing. Record MR.getInitializerSymbol() per-JD and run it directly by name lookup in runJDInitializers(). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RJk9KBVYSsZdLhNv2q3mfi
…symbol) The scraped $.<module>.__inits.0 symbol is MaterializationSideEffectsOnly and cannot be looked up after the module materialized via entry. Instead extract the init function's address directly from the link graph at post-fixup and run it. Also test a native-TLS (-fno-emulated-tls) variant for the TLS cases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RJk9KBVYSsZdLhNv2q3mfi
…ls_get_address The IR scraper makes the init symbol side-effects-only with no graph body; the runnable init code is clang's _GLOBAL__sub_I_<tu> (or the lone __cxx_global_var_init). Extract its address from the link graph. Also bind __emutls_get_address (windows-gnu always uses emulated TLS; compiler-rt has it but the host exe doesn't export it). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RJk9KBVYSsZdLhNv2q3mfi
Real add-ons failed to JIT-link with '.pdata: relocation target out of range of Pointer32 fixup': Windows x64 SEH unwind tables use 32-bit image-relative RVAs, but the default InProcessMemoryManager scatters segments so __ImageBase and the code land >2GB apart. Reserve one 1GiB contiguous slab via MapperJITLinkMemoryManager + InProcessMemoryMapper instead, keeping every segment and unwind section within RVA range. Applied to both the score JIT plugin and the jitmin harness. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RJk9KBVYSsZdLhNv2q3mfi
…ract only as fallback Real add-ons have a populated .ctors section AND clang's __cxx_global_var_init symbols, so the section-edge collection and the name-based init-extract were both collecting the same 6 initializers -> constructors ran twice -> crash. Fold the name-based extraction into registerObjectPlatformSections as a fallback that only fires when no .ctors/.CRT$XC*/.init_array edges were found (the pre-scraped .ll case). Real add-ons now run each constructor exactly once. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RJk9KBVYSsZdLhNv2q3mfi
…en't truncated After the slab + double-run fixes the real add-on compiles, links and runs its constructors, but crashes in score::registerPlugin -> __dynamic_cast jumping to a half-truncated pointer (0xffffff16_25ffffff). The small (default) code model emits 32-bit absolute relocations for data pointers (vtables, type_info); at the high slab load address those truncate and corrupt RTTI. Set CodeModel::Large on COFF (score plugin + jitmin) for 64-bit references throughout -- expected to fix cross-module dynamic_cast and the c05 exception-typeinfo crash too. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RJk9KBVYSsZdLhNv2q3mfi
…D from link order)
…mirror normal link)
…irection vmi crash?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Temporary diagnostics to pinpoint the silent Windows JIT-load failure (exit 127 after the add-on compiles). Surfaces ORC errors to stderr + brackets each load step / eager lookup. Once merged, continuous rebuilds and the template JIT-Windows test will print what fails instead of exit 127, so the follow-up fix is targeted. Will be reverted with that fix.
🤖 Generated with Claude Code