Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SIGSEGV with -flto #118725

Closed
illiminable opened this issue Dec 5, 2024 · 10 comments · Fixed by #119548
Closed

SIGSEGV with -flto #118725

illiminable opened this issue Dec 5, 2024 · 10 comments · Fixed by #119548
Labels
crash Prefer [crash-on-valid] or [crash-on-invalid] incomplete Issue not complete (e.g. missing a reproducer, build arguments, etc.) LTO Link time optimization (regular/full LTO or ThinLTO)

Comments

@illiminable
Copy link

Static linking with -flto on Arch linux with clang 18.1.8

Not able to get a minimal repro at the moment. Other possibly less common options

  "-std=c++20",
  "-nostdlib",
  "-nostartfiles",
  "-fno-exceptions",
  "-fno-rtti",

Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00007ee06170e69c in llvm::ConstantFoldConstant(llvm::Constant const*, llvm::DataLayout const&, llvm::TargetLibraryInfo const*) () from /usr/lib/libLLVM.so.18.1
#0 0x00007ee06170e69c in llvm::ConstantFoldConstant(llvm::Constant const*, llvm::DataLayout const&, llvm::TargetLibraryInfo const*) () from /usr/lib/libLLVM.so.18.1
#1 0x00007ee060abea1a in llvm::Evaluator::EvaluateBlock(llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, false, false, void, true>, false, false>, llvm::BasicBlock*&, bool&) () from /usr/lib/libLLVM.so.18.1
#2 0x00007ee060ac14e4 in llvm::Evaluator::EvaluateFunction(llvm::Function*, llvm::Constant*&, llvm::SmallVectorImplllvm::Constant* const&) () from /usr/lib/libLLVM.so.18.1
#3 0x00007ee061307930 in ?? () from /usr/lib/libLLVM.so.18.1
#4 0x00007ee061308634 in ?? () from /usr/lib/libLLVM.so.18.1
#5 0x00007ee060aa7649 in llvm::optimizeGlobalCtorsList(llvm::Module&, llvm::function_ref<bool (unsigned int, llvm::Function*)>) () from /usr/lib/libLLVM.so.18.1
#6 0x00007ee0613135f9 in llvm::GlobalOptPass::run(llvm::Module&, llvm::AnalysisManagerllvm::Module&) () from /usr/lib/libLLVM.so.18.1
#7 0x00007ee06411d177 in ?? () from /usr/lib/libLLVM.so.18.1
#8 0x00007ee05fbd767e in llvm::PassManager<llvm::Module, llvm::AnalysisManagerllvm::Module>::run(llvm::Module&, llvm::AnalysisManagerllvm::Module&) () from /usr/lib/libLLVM.so.18.1
#9 0x00007ee061a57995 in ?? () from /usr/lib/libLLVM.so.18.1
#10 0x00007ee061a591ff in llvm::lto::opt(llvm::lto::Config const&, llvm::TargetMachine*, unsigned int, llvm::Module&, bool, llvm::ModuleSummaryIndex*, llvm::ModuleSummaryIndex const*, std::vector<unsigned char, std::allocator > const&) () from /usr/lib/libLLVM.so.18.1
#11 0x00007ee061a5a582 in llvm::lto::backend(llvm::lto::Config const&, std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_deletellvm::CachedFileStream > > (unsigned int, llvm::Twine const&)>, unsigned int, llvm::Module&, llvm::ModuleSummaryIndex&) () from /usr/lib/libLLVM.so.18.1
#12 0x00007ee061a4ed49 in llvm::lto::LTO::runRegularLTO(std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_deletellvm::CachedFileStream > > (unsigned int, llvm::Twine const&)>) () from /usr/lib/libLLVM.so.18.1
#13 0x00007ee061a4f241 in llvm::lto::LTO::run(std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_deletellvm::CachedFileStream > > (unsigned int, llvm::Twine const&)>, std::function<llvm::Expected<std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_deletellvm::CachedFileStream > > (unsigned int, llvm::Twine const&)> > (unsigned int, llvm::StringRef, llvm::Twine const&)>) () from /usr/lib/libLLVM.so.18.1
#14 0x00007ee0678ce067 in ?? () from /usr/bin/../lib/LLVMgold.so
#15 0x00007ee0678cfd12 in ?? () from /usr/bin/../lib/LLVMgold.so
#16 0x000056f827567837 in ?? ()
#17 0x000056f82756f75f in ?? ()
#18 0x00007ee067a00e08 in ?? () from /usr/lib/libc.so.6
#19 0x00007ee067a00ecc in __libc_start_main () from /usr/lib/libc.so.6
#20 0x000056f82756ea65 in ?? ()

@EugeneZelenko EugeneZelenko added crash Prefer [crash-on-valid] or [crash-on-invalid] LTO Link time optimization (regular/full LTO or ThinLTO) and removed new issue labels Dec 5, 2024
@EugeneZelenko
Copy link
Contributor

Could you please try 19 or main branch?

@EugeneZelenko EugeneZelenko added the incomplete Issue not complete (e.g. missing a reproducer, build arguments, etc.) label Dec 5, 2024
@illiminable
Copy link
Author

I don't think 19 is packaged for arch yet. I'll see if I can build trunk later in the week.

Is it possible to just to disable this optimizeGlobalCtorsList or all of globalopt. I looked through --hidden-help and could not see an option like this.

@ms178
Copy link

ms178 commented Dec 5, 2024

@illiminable While it is not packaged by Arch yet, you could try the linked toolchain instead and use it via an environment variable which points llvm to the new path: https://mirrors.edge.kernel.org/pub/tools/llvm/

@illiminable
Copy link
Author

illiminable commented Dec 5, 2024

OK thanks I'll try. FWIW this is the approximate code pattern. And presumably its trying to optimize the fact that there are N unique symbols that "register" assigns true to but then never get used.

// Header File
class Functor {
   virtual void execImpl() = 0;
   void exec() { execImpl(); }
 };
 
 class Info {
   Functor* fn = nullptr;
 };
 
 class Registry {
   array<Info, 1024> fns;
   int count = 0;
   
   void register(Info&& f) {
     fns[count++] = f;
   }
   
   void exec() {
      for i in 0..count { fns[i].fn->exec(); }
   }
 };
 
 inline Registry reg;
 
 inline bool register(Functor* fn) {
   reg.register({.fn = fn});
   return true;
 }
 
 
 // REPEAT approx 10 each copies of the below in 10 different .cpp TU's
 class _uniquesymbol_ : public Functor {
   void execImpl() override;
 };
 
 // Instance of the derived functor class
 _uniquesymbol_ _uniquesymbol__instance;
 
 // _uniquesymbol__flag is always true and never used. Theres probably a better
 // way to do this?
 const bool _uniquesymbol__flag = register(&_uniquesymbol__instance);
 
 void _uniquesymbol_::execImpl() {
   // do stuff
 }
 
 // END REPEAT
 
 
 // Usage...
 reg.exec();

@illiminable
Copy link
Author

@ms178 The toolchain didn't work because it doesn't contain LLVMgold.so

I was able to build from the 19.1.5 branch in debug and can repro. It's only on one target. This is the assert output

ld.gold: /mnt/local/src/third_party/github/llvm/llvm-project/llvm/include/llvm/Support/Casting.h:109: static bool llvm::isa_impl_cl<To, const From*>::doit(const From*) [with To = llvm::ConstantVector; From = llvm::Constant]: Assertion `Val && "isa<> used on a null pointer"' failed.

And a better symbolized stack

#0 0x00007c11cae473f4 in ?? () from /usr/lib/libc.so.6
#0 0x00007c11cae473f4 in ?? () from /usr/lib/libc.so.6
#1 0x00007c11cadee120 in raise () from /usr/lib/libc.so.6
#2 0x00007c11cadd54c3 in abort () from /usr/lib/libc.so.6
#3 0x00007c11cadd53df in ?? () from /usr/lib/libc.so.6
#4 0x00007c11cade6177 in __assert_fail () from /usr/lib/libc.so.6
#5 0x00007c11c329c245 in llvm::isa_impl_cl<llvm::ConstantVector, llvm::Constant const*>::doit (Val=0x0) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/include/llvm/Support/Casting.h:109
#6 0x00007c11c329bd99 in llvm::isa_impl_wrap<llvm::ConstantVector, llvm::Constant const*, llvm::Constant const*>::doit (Val=@0x7ffd009f71a0: 0x0) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/include/llvm/Support/Casting.h:137
#7 0x00007c11c329b45b in llvm::isa_impl_wrap<llvm::ConstantVector, llvm::Constant const* const, llvm::Constant const*>::doit (Val=@0x7ffd009f71f0: 0x0) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/include/llvm/Support/Casting.h:129
#8 0x00007c11c329a6b6 in llvm::CastIsPossible<llvm::ConstantVector, llvm::Constant const*, void>::isPossible (f=@0x7ffd009f71f0: 0x0) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/include/llvm/Support/Casting.h:257
#9 0x00007c11c5ccd903 in llvm::CastInfo<llvm::ConstantVector, llvm::Constant const* const, void>::isPossible (f=@0x7ffd009f7248: 0x0) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/include/llvm/Support/Casting.h:509
#10 0x00007c11c5ccd3d8 in llvm::isa<llvm::ConstantVector, llvm::Constant const*> (Val=@0x7ffd009f7248: 0x0) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/include/llvm/Support/Casting.h:549
#11 0x00007c11c5f8be6e in (anonymous namespace)::ConstantFoldConstantImpl (C=0x0, DL=..., TLI=0x5d4a86076c38, FoldedOps=...) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/lib/Analysis/ConstantFolding.cpp:1078
#12 0x00007c11c5f8c5d3 in llvm::ConstantFoldConstant (C=0x0, DL=..., TLI=0x5d4a86076c38) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/lib/Analysis/ConstantFolding.cpp:1163
#13 0x00007c11c5cb7bdc in llvm::Evaluator::EvaluateBlock (this=0x7ffd009f7930, CurInst=..., NextBB=@0x7ffd009f76e0: 0x0, StrippedPointerCastsForAliasAnalysis=@0x7ffd009f76d0: false) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/lib/Transforms/Utils/Evaluator.cpp:610
#14 0x00007c11c5cb7fd8 in llvm::Evaluator::EvaluateFunction (this=0x7ffd009f7930, F=0x5d4a85ccc618, RetVal=@0x7ffd009f78a8: 0x7ffd009f7ae0, ActualArgs=...) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/lib/Transforms/Utils/Evaluator.cpp:660
#15 0x00007c11c4f410a8 in EvaluateStaticConstructor (F=0x5d4a85ccc618, DL=..., TLI=0x5d4a86076c38) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/lib/Transforms/IPO/GlobalOpt.cpp:2080
#16 0x00007c11c4f42bf7 in operator() (__closure=0x7ffd009f7e90, Priority=65535, F=0x5d4a85ccc618) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/lib/Transforms/IPO/GlobalOpt.cpp:2524
#17 0x00007c11c4f43f3b in llvm::function_ref<bool(unsigned int, llvm::Function*)>::callback_fn<optimizeGlobalsInModule(llvm::Module&, const llvm::DataLayout&, llvm::function_refllvm::TargetLibraryInfo&(llvm::Function&), llvm::function_refllvm::TargetTransformInfo&(llvm::Function&), llvm::function_refllvm::BlockFrequencyInfo&(llvm::Function&), llvm::function_refllvm::DominatorTree&(llvm::Function&), llvm::function_ref<void(llvm::Function&)>, llvm::function_ref<void(llvm::Function&)>)::<lambda(uint32_t, llvm::Function*)> >(intptr_t, unsigned int, llvm::Function ) (callable=140724613906064, params#0=65535, params#1=0x5d4a85ccc618) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:45
#18 0x00007c11c5c95103 in llvm::function_ref<bool(unsigned int, llvm::Function
)>::operator() (this=0x7ffd009f7cc0, params#0=65535, params#1=0x5d4a85ccc618) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:68
#19 0x00007c11c5c92754 in llvm::optimizeGlobalCtorsList (M=..., ShouldRemove=...) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/lib/Transforms/Utils/CtorUtils.cpp:138
#20 0x00007c11c4f4309c in optimizeGlobalsInModule(llvm::Module &, const llvm::DataLayout &, llvm::function_refllvm::TargetLibraryInfo&(llvm::Function&), llvm::function_refllvm::TargetTransformInfo&(llvm::Function&), llvm::function_refllvm::BlockFrequencyInfo&(llvm::Function&), llvm::function_refllvm::DominatorTree&(llvm::Function&), llvm::function_ref<void(llvm::Function&)>, llvm::function_ref<void(llvm::Function&)>) (M=..., DL=..., GetTLI=..., GetTTI=..., GetBFI=..., LookupDomTree=..., ChangedCFGCallback=..., DeleteFnCallback=...) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/lib/Transforms/IPO/GlobalOpt.cpp:2520
#21 0x00007c11c4f435e0 in llvm::GlobalOptPass::run (this=0x5d4a85c13138, M=..., AM=...) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/lib/Transforms/IPO/GlobalOpt.cpp:2583
#22 0x00007c11c4366477 in llvm::detail::PassModel<llvm::Module, llvm::GlobalOptPass, llvm::AnalysisManagerllvm::Module>::run(llvm::Module&, llvm::AnalysisManagerllvm::Module&) (this=0x5d4a85c13130, IR=..., AM=...) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:90
#23 0x00007c11c6e2f349 in llvm::PassManager<llvm::Module, llvm::AnalysisManagerllvm::Module>::run(llvm::Module&, llvm::AnalysisManagerllvm::Module&) (this=0x7ffd009f8300, IR=..., AM=...) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/include/llvm/IR/PassManagerImpl.h:81
#24 0x00007c11c3934968 in runNewPMPasses (Conf=..., Mod=..., TM=0x5d4a85edf0b0, OptLevel=3, IsThinLTO=false, ExportSummary=0x5d4a85bc6d18, ImportSummary=0x0) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/lib/LTO/LTOBackend.cpp:338
#25 0x00007c11c3934b94 in llvm::lto::opt (Conf=..., TM=0x5d4a85edf0b0, Task=0, Mod=..., IsThinLTO=false, ExportSummary=0x5d4a85bc6d18, ImportSummary=0x0, CmdArgs=std::vector of length 0, capacity 0) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/lib/LTO/LTOBackend.cpp:363
#26 0x00007c11c3936054 in llvm::lto::backend (C=..., AddStream=..., ParallelCodeGenParallelismLevel=1, Mod=..., CombinedIndex=...) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/lib/LTO/LTOBackend.cpp:517
#27 0x00007c11c38e855d in llvm::lto::LTO::runRegularLTO (this=0x5d4a85bc6710, AddStream=...) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/lib/LTO/LTO.cpp:1354
#28 0x00007c11c38e746b in llvm::lto::LTO::run (this=0x5d4a85bc6710, AddStream=..., Cache=...) at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/lib/LTO/LTO.cpp:1186
#29 0x00007c11c3255536 in runLTO () at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/tools/gold/gold-plugin.cpp:1111
#30 0x00007c11c3255a0d in allSymbolsReadHook () at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/tools/gold/gold-plugin.cpp:1148
#31 0x00007c11c3255c19 in all_symbols_read_hook () at /mnt/local/src/third_party/github/llvm/llvm-project/llvm/tools/gold/gold-plugin.cpp:1173
#32 0x00005d4a6c4d9154 in ?? ()
#33 0x00005d4a6c5138d0 in ?? ()
#34 0x00005d4a6c3fc49a in ?? ()
#35 0x00007c11cadd6e08 in ?? () from /usr/lib/libc.so.6
#36 0x00007c11cadd6ecc in __libc_start_main () from /usr/lib/libc.so.6
#37 0x00005d4a6c3ff985 in ?? ()

@ms178
Copy link

ms178 commented Dec 6, 2024

@illiminable Thanks for letting me know. Unfortunately I am not a developer and cannot help you to debug this problem further.

@illiminable
Copy link
Author

illiminable commented Dec 6, 2024

I debugged a little bit, but I don't fully understand this code.

In EvaluateBlock the issue is that after the various branches the code falls out to this block at 609 with InstResult still null. All the other branches usually check InstResult and return false. ConstantFoldConstant will assert or crash if the first parameter is null in the call from 610. I also tried just guarding this conditino with !InstResult but that doesn't seem right since it triggers another assert later "Assertion `R && "Reference to an uncomputed value!"'.

https://github.com/llvm/llvm-project/blob/llvmorg-19.1.5/llvm/lib/Transforms/Utils/Evaluator.cpp#L610

The bug only only occurs when the code hits the branch on 556. Strangely the debug log here says both branches of the if are success. I don't know if it's a copy paste error or if maybe the code should just return true after 558, but given the rest of the code this doesn't seem right.

But returning false in the line 556 branch seems to fix the crash and the resulting program seems to work fine.

https://github.com/llvm/llvm-project/blob/llvmorg-19.1.5/llvm/lib/Transforms/Utils/Evaluator.cpp#L556

Someone who understands the code better should evaluate though.

@illiminable
Copy link
Author

I used llvm-reduce to reduce the bitcode and when i looked at what was left it was basically __cxa_guard_acquire and I realized that while bootstrapping i defined it with the wrong return type. So since I violated the ABI I guess my fault.

Not sure if there is still an underlying issue here someone wants to fix. ie. would be better to error or ignore than crash. But it seems pretty unlikely someone else will hit at least this specific cause of the problem.

Can probably close if this corner case is not important.

@nikic
Copy link
Contributor

nikic commented Dec 6, 2024

Could you please share the reduced bitcode? (Or IR after running it through llvm-dis.)

@illiminable
Copy link
Author

reduced.zip

This is the reduced.bc

nikic added a commit to nikic/llvm-project that referenced this issue Dec 11, 2024
The global ctor evaluator tries to evalute function calls where the
call function type and function type do not match, by performing
bitcasts. This currently causes a crash when calling a void
function with non-void return type.

I've opted to remove this functionality entirely rather than fixing
this specific case. With opaque pointers, there shouldn't be a
legitimate use case for this anymore, as we don't need to look
through pointer type casts. Doing other bitcasts is very iffy
because it ignores ABI considerations. We should at least leave
adjusting the signatures to make them line up to InstCombine
(which also does some iffy things, but is at least somewhat more
constrained).

Fixes llvm#118725.
nikic added a commit that referenced this issue Dec 12, 2024
…119548)

The global ctor evaluator tries to evalute function calls where the call
function type and function type do not match, by performing bitcasts.
This currently causes a crash when calling a void function with non-void
return type.

I've opted to remove this functionality entirely rather than fixing this
specific case. With opaque pointers, there shouldn't be a legitimate use
case for this anymore, as we don't need to look through pointer type
casts. Doing other bitcasts is very iffy because it ignores ABI
considerations. We should at least leave adjusting the signatures to
make them line up to InstCombine (which also does some iffy things, but
is at least somewhat more constrained).

Fixes #118725.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crash Prefer [crash-on-valid] or [crash-on-invalid] incomplete Issue not complete (e.g. missing a reproducer, build arguments, etc.) LTO Link time optimization (regular/full LTO or ThinLTO)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants