LLVMOrcLLJITLookup crashing (segfault)

Hi!

I am trying to utilize the Orcv2 C API. Everything goes smooth, initialized and well-formed (at least I assert for null pointers everywhere), till the point I try to lookup a symbol with LLVMOrcLLJITLookup: I receive a SIGSEGV.

Providing the backtrace:

  • thread #1, name = ‘tarantool’, stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
  • frame #0: 0x0000000001a88db0 tarantoolllvm::LLVMContext::getDiagHandlerPtr() const frame #1: 0x0000000001a959d4 tarantoolllvm::legacy::PassManagerImpl::run(llvm::Module&) + 628
    frame #2: 0x0000000000c5fa0e tarantoolllvm::orc::SimpleCompiler::operator()(llvm::Module&) + 366 frame #3: 0x0000000000c6fd4e tarantooldecltype(auto) llvm::orc::ThreadSafeModule::withModuleDollvm::orc::IRCompileLayer::IRCompiler&(llvm::orc::IRCompileLayer::IRCompiler&) + 94
    frame #4: 0x0000000000c6fa05 tarantoolllvm::orc::IRCompileLayer::emit(std::unique_ptr<llvm::orc::MaterializationResponsibility, std::default_delete<llvm::orc::MaterializationResponsibility> >, llvm::orc::ThreadSafeModule) + 37 frame #5: 0x0000000000c6fff7 tarantoolllvm::orc::IRTransformLayer::emit(std::unique_ptr<llvm::orc::MaterializationResponsibility, std::default_deletellvm::orc::MaterializationResponsibility >, llvm::orc::ThreadSafeModule) + 199
    frame #6: 0x0000000000c6fff7 tarantoolllvm::orc::IRTransformLayer::emit(std::unique_ptr<llvm::orc::MaterializationResponsibility, std::default_delete<llvm::orc::MaterializationResponsibility> >, llvm::orc::ThreadSafeModule) + 199 frame #7: 0x0000000000c396a2 tarantoolllvm::orc::BasicIRLayerMaterializationUnit::materialize(std::unique_ptr<llvm::orc::MaterializationResponsibility, std::default_deletellvm::orc::MaterializationResponsibility >) + 274
    frame #8: 0x0000000000c1fb4b tarantoolllvm::orc::ExecutionSession::materializeOnCurrentThread(std::unique_ptr<llvm::orc::MaterializationUnit, std::default_delete<llvm::orc::MaterializationUnit> >, std::unique_ptr<llvm::orc::MaterializationResponsibility, std::default_delete<llvm::orc::MaterializationResponsibility> >) + 27 frame #9: 0x0000000000c29a61 tarantoolstd::_Function_handler<void (std::unique_ptr<llvm::orc::MaterializationUnit, std::default_deletellvm::orc::MaterializationUnit >, std::unique_ptr<llvm::orc::MaterializationResponsibility, std::default_deletellvm::orc::MaterializationResponsibility >), void ()(std::unique_ptr<llvm::orc::MaterializationUnit, std::default_deletellvm::orc::MaterializationUnit >, std::unique_ptr<llvm::orc::MaterializationResponsibility, std::default_deletellvm::orc::MaterializationResponsibility >)>::_M_invoke(std::_Any_data const&, std::unique_ptr<llvm::orc::MaterializationUnit, std::default_deletellvm::orc::MaterializationUnit >&&, std::unique_ptr<llvm::orc::MaterializationResponsibility, std::default_deletellvm::orc::MaterializationResponsibility >&&) + 49
    frame #10: 0x0000000000c20d31 tarantoolllvm::orc::ExecutionSession::dispatchOutstandingMUs() + 353 frame #11: 0x0000000000c23327 tarantoolllvm::orc::ExecutionSession::OL_completeLookup(std::unique_ptr<llvm::orc::InProgressLookupState, std::default_deletellvm::orc::InProgressLookupState >, std::shared_ptrllvm::orc::AsynchronousSymbolQuery, std::function<void (llvm::DenseMap<llvm::orc::JITDylib
    , llvm::DenseSet<llvm::orc::SymbolStringPtr, llvm::DenseMapInfollvm::orc::SymbolStringPtr >, llvm::DenseMapInfollvm::orc::JITDylib*, llvm::detail::DenseMapPair<llvm::orc::JITDylib*, llvm::DenseSet<llvm::orc::SymbolStringPtr, llvm::DenseMapInfollvm::orc::SymbolStringPtr > > > const&)>) + 4711
    frame #12: 0x0000000000c308fb tarantoolllvm::orc::InProgressFullLookupState::complete(std::unique_ptr<llvm::orc::InProgressLookupState, std::default_delete<llvm::orc::InProgressLookupState> >) + 251 frame #13: 0x0000000000c14a0a tarantoolllvm::orc::ExecutionSession::OL_applyQueryPhase1(std::unique_ptr<llvm::orc::InProgressLookupState, std::default_deletellvm::orc::InProgressLookupState >, llvm::Error) + 2010
    frame #14: 0x0000000000c12c8c tarantoolllvm::orc::ExecutionSession::lookup(llvm::orc::LookupKind, std::vector<std::pair<llvm::orc::JITDylib*, llvm::orc::JITDylibLookupFlags>, std::allocator<std::pair<llvm::orc::JITDylib*, llvm::orc::JITDylibLookupFlags> > > const&, llvm::orc::SymbolLookupSet, llvm::orc::SymbolState, llvm::unique_function<void (llvm::Expected<llvm::DenseMap<llvm::orc::SymbolStringPtr, llvm::JITEvaluatedSymbol, llvm::DenseMapInfo<llvm::orc::SymbolStringPtr>, llvm::detail::DenseMapPair<llvm::orc::SymbolStringPtr, llvm::JITEvaluatedSymbol> > >)>, std::function<void (llvm::DenseMap<llvm::orc::JITDylib*, llvm::DenseSet<llvm::orc::SymbolStringPtr, llvm::DenseMapInfo<llvm::orc::SymbolStringPtr> >, llvm::DenseMapInfo<llvm::orc::JITDylib*>, llvm::detail::DenseMapPair<llvm::orc::JITDylib*, llvm::DenseSet<llvm::orc::SymbolStringPtr, llvm::DenseMapInfo<llvm::orc::SymbolStringPtr> > > > const&)>) + 556 frame #15: 0x0000000000c20fc6 tarantoolllvm::orc::ExecutionSession::lookup(std::vector<std::pair<llvm::orc::JITDylib*, llvm::orc::JITDylibLookupFlags>, std::allocator<std::pair<llvm::orc::JITDylib*, llvm::orc::JITDylibLookupFlags> > > const&, llvm::orc::SymbolLookupSet const&, llvm::orc::LookupKind, llvm::orc::SymbolState, std::function<void (llvm::DenseMap<llvm::orc::JITDylib*, llvm::DenseSet<llvm::orc::SymbolStringPtr, llvm::DenseMapInfollvm::orc::SymbolStringPtr >, llvm::DenseMapInfollvm::orc::JITDylib*, llvm::detail::DenseMapPair<llvm::orc::JITDylib*, llvm::DenseSet<llvm::orc::SymbolStringPtr, llvm::DenseMapInfollvm::orc::SymbolStringPtr > > > const&)>) + 486
    frame #16: 0x0000000000c2154e tarantoolllvm::orc::ExecutionSession::lookup(std::vector<std::pair<llvm::orc::JITDylib*, llvm::orc::JITDylibLookupFlags>, std::allocator<std::pair<llvm::orc::JITDylib*, llvm::orc::JITDylibLookupFlags> > > const&, llvm::orc::SymbolStringPtr, llvm::orc::SymbolState) + 302 frame #17: 0x0000000000c3b937 tarantoolllvm::orc::LLJIT::lookupLinkerMangled(llvm::orc::JITDylib&, llvm::orc::SymbolStringPtr) + 119
    frame #18: 0x0000000000c08b36 tarantoolllvm::orc::LLJIT::lookup(llvm::orc::JITDylib&, llvm::StringRef) + 166 frame #19: 0x0000000000c0770b tarantoolLLVMOrcLLJITLookup + 59
    frame #20: 0x0000000000778900 tarantool`llvm_exec_compiled_expr_list(ctx=0x0000000003271510, fn_id=0, vdbe=0x0000000002db9e18) at llvm_jit.c:443:8

Apparently, the problem with the segfault is the attempt to access the DiagHandler, though I explicitly set it.

My code can be viewed here:

https://github.com/CuriousGeorgiy/tarantool/blob/CuriousGeorgiy/sql-vdbe-jit/src/box/sql/llvm_jit.h

https://github.com/CuriousGeorgiy/tarantool/blob/CuriousGeorgiy/sql-vdbe-jit/src/box/sql/llvm_jit.c

I understand the code I provided may be sophisticated enough, so if there is any additional information or context I can provide that would be helpful, please, let me know.

Also, this is my first time communicating via a mailing list, so, please, let me know if I am missing on something.

Have you tried running this with assertions on? Also my C knowledge isn’t the best but I would have thought it should be LLVMContextSetDiagnosticHandler(m_ctx, &llvm_diag_handler, NULL);

Your handling of TSContext and TSModule seems a bit, I think you should create one TSContext per TSModule, instead of having a global one that seems to be shared between modules.

The module here should use the same context as the ts_context itself https://github.com/CuriousGeorgiy/tarantool/blob/f73f01ef2699704e9e6fd6dd294d13c299c4627f/src/box/sql/llvm_jit.c#L1232
and after the tsm is created you can dispose the tscontext, since the context is now owned by the module.

Hi, Valentin!

Thank you for your reply!

Have you tried running this with assertions on?

Yes.

Also my C knowledge isn’t the best but I would have thought it should be LLVMContextSetDiagnosticHandler(m_ctx, &llvm_diag_handler, NULL);

Actually, &llvm_diag_handler and llvm_diag_handler are equivalent in ‘C’.

Your handling of TSContext and TSModule seems a bit, I think you should create one TSContext per TSModule, instead of having a global one that seems to be shared between modules.
The module here should use the same context as the ts_context itself https://github.com/CuriousGeorgiy/tarantool/blob/f73f01ef2699704e9e6fd6dd294d13c299c4627f/src/box/sql/llvm_jit.c#L1232
and after the tsm is created you can dispose the tscontext, since the context is now owned by the module.

Fixed that, thank you for the suggestion.

Actually, the problem turned out to be the ‘free’ here:
https://github.com/CuriousGeorgiy/tarantool/blob/f73f01ef2699704e9e6fd6dd294d13c299c4627f/src/box/sql/llvm_jit.c#L1234

Previously I transferred the LLVM module ownership under construction between a ‘build’ context and an ‘execution’ context, so I allocated memory for the reference. Did not clean this spot up after refactoring, thus the bug and no diagnostic information.

Thank you for your time and help in pointing out the suspicious area for me.

I apologize for bothering about a bug in my memory management, not related to the LLVM C API.