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

LLVM ERROR: Broken module found, compilation aborted! when building Firefox with full LTO #68929

Open
glandium opened this issue Oct 12, 2023 · 12 comments
Labels
debuginfo LTO Link time optimization (regular/full LTO or ThinLTO)

Comments

@glandium
Copy link
Contributor

This didn't happen before 8840da2.

STR:

llvm.dbg.declare has larger fragment size than alloca size 
  call void @llvm.dbg.declare(metadata ptr %8, metadata !26454674, metadata !DIExpression()), !dbg !26454731
llvm.dbg.declare has larger fragment size than alloca size 
  call void @llvm.dbg.declare(metadata ptr %17, metadata !26462027, metadata !DIExpression()), !dbg !26462037
llvm.dbg.declare has larger fragment size than alloca size 
  call void @llvm.dbg.declare(metadata ptr %8, metadata !26468121, metadata !DIExpression()), !dbg !26468178
llvm.dbg.declare has larger fragment size than alloca size 
  call void @llvm.dbg.declare(metadata ptr %17, metadata !26475461, metadata !DIExpression()), !dbg !26475471
llvm.dbg.declare has larger fragment size than alloca size 
  call void @llvm.dbg.declare(metadata ptr %8, metadata !26481438, metadata !DIExpression()), !dbg !26481495
llvm.dbg.declare has larger fragment size than alloca size 
  call void @llvm.dbg.declare(metadata ptr %17, metadata !26488783, metadata !DIExpression()), !dbg !26488793
llvm.dbg.declare has larger fragment size than alloca size 
  call void @llvm.dbg.declare(metadata ptr %8, metadata !26494766, metadata !DIExpression()), !dbg !26494823
llvm.dbg.declare has larger fragment size than alloca size 
  call void @llvm.dbg.declare(metadata ptr %17, metadata !26502101, metadata !DIExpression()), !dbg !26502111
llvm.dbg.declare has larger fragment size than alloca size 
  call void @llvm.dbg.declare(metadata ptr %8, metadata !26508252, metadata !DIExpression()), !dbg !26508309
llvm.dbg.declare has larger fragment size than alloca size 
  call void @llvm.dbg.declare(metadata ptr %18, metadata !26516098, metadata !DIExpression()), !dbg !26516124
LLVM ERROR: Broken module found, compilation aborted!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /tmp/gecko/clang/bin/ld.lld @response.txt
 #0 0x00007f765d87c8a7 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x28398a7)
 #1 0x00007f765d87cd8b SignalHandler(int) Signals.cpp:0:0
 #2 0x00007f765ab7bfd0 (/lib/x86_64-linux-gnu/libc.so.6+0x3bfd0)
 #3 0x00007f765abcad3c __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #4 0x00007f765ab7bf32 raise ./signal/../sysdeps/posix/raise.c:27:6
 #5 0x00007f765ab66472 abort ./stdlib/abort.c:81:7
 #6 0x00007f765d818698 llvm::report_fatal_error(llvm::Twine const&, bool) (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x27d5698)
 #7 0x00007f765cb90bd5 (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x1b4dbd5)
 #8 0x00007f765d96b097 (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x2928097)
 #9 0x00007f765e47c6ed llvm::detail::PassModel<llvm::Module, llvm::VerifierPass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) LTOBackend.cpp:0:0
#10 0x00007f765d555bdc llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x2512bdc)
#11 0x00007f765e477af4 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<unsigned char>> const&) (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x3434af4)
#12 0x00007f765e479594 llvm::lto::backend(llvm::lto::Config const&, std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>, unsigned int, llvm::Module&, llvm::ModuleSummaryIndex&) (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x3436594)
#13 0x00007f765e46f30f llvm::lto::LTO::runRegularLTO(std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>) (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x342c30f)
#14 0x00007f765e46eb73 llvm::lto::LTO::run(std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>, std::function<llvm::Expected<std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>> (unsigned int, llvm::StringRef, llvm::Twine const&)>) (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x342bb73)
#15 0x00005582ad0e6860 lld::elf::BitcodeCompiler::compile() (/tmp/gecko/clang/bin/ld.lld+0x25d860)
#16 0x00005582ad040549 lld::elf::LinkerDriver::link(llvm::opt::InputArgList&) (/tmp/gecko/clang/bin/ld.lld+0x1b7549)
#17 0x00005582ad02fa34 lld::elf::LinkerDriver::linkerMain(llvm::ArrayRef<char const*>) (/tmp/gecko/clang/bin/ld.lld+0x1a6a34)
#18 0x00005582ad02dfe0 lld::elf::link(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, bool, bool) (/tmp/gecko/clang/bin/ld.lld+0x1a4fe0)
#19 0x00005582acf72845 lld::unsafeLldMain(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, llvm::ArrayRef<lld::DriverDef>, bool) (/tmp/gecko/clang/bin/ld.lld+0xe9845)
#20 0x00005582acf70182 lld_main(int, char**, llvm::ToolContext const&) (/tmp/gecko/clang/bin/ld.lld+0xe7182)
#21 0x00005582acf7004e main (/tmp/gecko/clang/bin/ld.lld+0xe704e)
#22 0x00007f765ab671ca __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3
#23 0x00007f765ab67285 call_init ./csu/../csu/libc-start.c:128:20
#24 0x00007f765ab67285 __libc_start_main ./csu/../csu/libc-start.c:347:5
#25 0x00005582acf71b72 _start (/tmp/gecko/clang/bin/ld.lld+0xe8b72)

Cc: @nikic

(It's also unfortunate that it doesn't tell what specific module is broken)

@EugeneZelenko EugeneZelenko added LTO Link time optimization (regular/full LTO or ThinLTO) and removed new issue labels Oct 12, 2023
@nikic
Copy link
Contributor

nikic commented Oct 13, 2023

The verifier error already occurs on libxul.so.0.0.preopt.bc, so I think that means that one of the inputs is already broken or it happens during module merging.

@nikic
Copy link
Contributor

nikic commented Oct 13, 2023

Running something like find . -name '*.o' -print0 | xargs -0 -L1 -P16 ~/repos/llvm-project/build/bin/opt -disable-output 2>&1 | grep "larger fragment doesn't give any results, so I think that means it must happen merging modules?

The relevant allocas look like this:

  %8 = alloca %struct.AVPacket.153109, align 8

I'm not sure how to debug this further.

@teresajohnson
Copy link
Contributor

This is also breaking some of our ThinLTO builds (8840da2#commitcomment-129914039)

Could it be reverted while the fix is investigated?

It looks like somehow the debug declare and alloca get out of sync when the IRMover/IRLinker is invoked?

For regular LTO like in the case described here, the IRMover is invoked from LTO each time a module is linked:

return RegularLTO.Mover->move(std::move(Mod.M), Keep, nullptr,
. ThinLTO does something similar during importing, but I think it will probably be more straightforward to track down with the full LTO case since the IR merging happens immediately upon the linker adding modules to LTO.

@nikic
Copy link
Contributor

nikic commented Oct 13, 2023

@teresajohnson Feel free to revert, I can't do it myself right now.

nikic added a commit that referenced this issue Oct 16, 2023
…riable fragment size"

This reverts commit 8840da2.

This results in verifier failures during LTO, see #68929.
@llvmbot
Copy link
Member

llvmbot commented Oct 16, 2023

@llvm/issue-subscribers-debuginfo

Author: Mike Hommey (glandium)

This didn't happen before 8840da2.

STR:

llvm.dbg.declare has larger fragment size than alloca size 
  call void @<!-- -->llvm.dbg.declare(metadata ptr %8, metadata !26454674, metadata !DIExpression()), !dbg !26454731
llvm.dbg.declare has larger fragment size than alloca size 
  call void @<!-- -->llvm.dbg.declare(metadata ptr %17, metadata !26462027, metadata !DIExpression()), !dbg !26462037
llvm.dbg.declare has larger fragment size than alloca size 
  call void @<!-- -->llvm.dbg.declare(metadata ptr %8, metadata !26468121, metadata !DIExpression()), !dbg !26468178
llvm.dbg.declare has larger fragment size than alloca size 
  call void @<!-- -->llvm.dbg.declare(metadata ptr %17, metadata !26475461, metadata !DIExpression()), !dbg !26475471
llvm.dbg.declare has larger fragment size than alloca size 
  call void @<!-- -->llvm.dbg.declare(metadata ptr %8, metadata !26481438, metadata !DIExpression()), !dbg !26481495
llvm.dbg.declare has larger fragment size than alloca size 
  call void @<!-- -->llvm.dbg.declare(metadata ptr %17, metadata !26488783, metadata !DIExpression()), !dbg !26488793
llvm.dbg.declare has larger fragment size than alloca size 
  call void @<!-- -->llvm.dbg.declare(metadata ptr %8, metadata !26494766, metadata !DIExpression()), !dbg !26494823
llvm.dbg.declare has larger fragment size than alloca size 
  call void @<!-- -->llvm.dbg.declare(metadata ptr %17, metadata !26502101, metadata !DIExpression()), !dbg !26502111
llvm.dbg.declare has larger fragment size than alloca size 
  call void @<!-- -->llvm.dbg.declare(metadata ptr %8, metadata !26508252, metadata !DIExpression()), !dbg !26508309
llvm.dbg.declare has larger fragment size than alloca size 
  call void @<!-- -->llvm.dbg.declare(metadata ptr %18, metadata !26516098, metadata !DIExpression()), !dbg !26516124
LLVM ERROR: Broken module found, compilation aborted!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /tmp/gecko/clang/bin/ld.lld @<!-- -->response.txt
 #<!-- -->0 0x00007f765d87c8a7 llvm::sys::PrintStackTrace(llvm::raw_ostream&amp;, int) (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x28398a7)
 #<!-- -->1 0x00007f765d87cd8b SignalHandler(int) Signals.cpp:0:0
 #<!-- -->2 0x00007f765ab7bfd0 (/lib/x86_64-linux-gnu/libc.so.6+0x3bfd0)
 #<!-- -->3 0x00007f765abcad3c __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #<!-- -->4 0x00007f765ab7bf32 raise ./signal/../sysdeps/posix/raise.c:27:6
 #<!-- -->5 0x00007f765ab66472 abort ./stdlib/abort.c:81:7
 #<!-- -->6 0x00007f765d818698 llvm::report_fatal_error(llvm::Twine const&amp;, bool) (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x27d5698)
 #<!-- -->7 0x00007f765cb90bd5 (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x1b4dbd5)
 #<!-- -->8 0x00007f765d96b097 (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x2928097)
 #<!-- -->9 0x00007f765e47c6ed llvm::detail::PassModel&lt;llvm::Module, llvm::VerifierPass, llvm::PreservedAnalyses, llvm::AnalysisManager&lt;llvm::Module&gt;&gt;::run(llvm::Module&amp;, llvm::AnalysisManager&lt;llvm::Module&gt;&amp;) LTOBackend.cpp:0:0
#<!-- -->10 0x00007f765d555bdc llvm::PassManager&lt;llvm::Module, llvm::AnalysisManager&lt;llvm::Module&gt;&gt;::run(llvm::Module&amp;, llvm::AnalysisManager&lt;llvm::Module&gt;&amp;) (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x2512bdc)
#<!-- -->11 0x00007f765e477af4 llvm::lto::opt(llvm::lto::Config const&amp;, llvm::TargetMachine*, unsigned int, llvm::Module&amp;, bool, llvm::ModuleSummaryIndex*, llvm::ModuleSummaryIndex const*, std::vector&lt;unsigned char, std::allocator&lt;unsigned char&gt;&gt; const&amp;) (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x3434af4)
#<!-- -->12 0x00007f765e479594 llvm::lto::backend(llvm::lto::Config const&amp;, std::function&lt;llvm::Expected&lt;std::unique_ptr&lt;llvm::CachedFileStream, std::default_delete&lt;llvm::CachedFileStream&gt;&gt;&gt; (unsigned int, llvm::Twine const&amp;)&gt;, unsigned int, llvm::Module&amp;, llvm::ModuleSummaryIndex&amp;) (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x3436594)
#<!-- -->13 0x00007f765e46f30f llvm::lto::LTO::runRegularLTO(std::function&lt;llvm::Expected&lt;std::unique_ptr&lt;llvm::CachedFileStream, std::default_delete&lt;llvm::CachedFileStream&gt;&gt;&gt; (unsigned int, llvm::Twine const&amp;)&gt;) (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x342c30f)
#<!-- -->14 0x00007f765e46eb73 llvm::lto::LTO::run(std::function&lt;llvm::Expected&lt;std::unique_ptr&lt;llvm::CachedFileStream, std::default_delete&lt;llvm::CachedFileStream&gt;&gt;&gt; (unsigned int, llvm::Twine const&amp;)&gt;, std::function&lt;llvm::Expected&lt;std::function&lt;llvm::Expected&lt;std::unique_ptr&lt;llvm::CachedFileStream, std::default_delete&lt;llvm::CachedFileStream&gt;&gt;&gt; (unsigned int, llvm::Twine const&amp;)&gt;&gt; (unsigned int, llvm::StringRef, llvm::Twine const&amp;)&gt;) (/tmp/gecko/clang/bin/../lib/libLLVM-18git.so+0x342bb73)
#<!-- -->15 0x00005582ad0e6860 lld::elf::BitcodeCompiler::compile() (/tmp/gecko/clang/bin/ld.lld+0x25d860)
#<!-- -->16 0x00005582ad040549 lld::elf::LinkerDriver::link(llvm::opt::InputArgList&amp;) (/tmp/gecko/clang/bin/ld.lld+0x1b7549)
#<!-- -->17 0x00005582ad02fa34 lld::elf::LinkerDriver::linkerMain(llvm::ArrayRef&lt;char const*&gt;) (/tmp/gecko/clang/bin/ld.lld+0x1a6a34)
#<!-- -->18 0x00005582ad02dfe0 lld::elf::link(llvm::ArrayRef&lt;char const*&gt;, llvm::raw_ostream&amp;, llvm::raw_ostream&amp;, bool, bool) (/tmp/gecko/clang/bin/ld.lld+0x1a4fe0)
#<!-- -->19 0x00005582acf72845 lld::unsafeLldMain(llvm::ArrayRef&lt;char const*&gt;, llvm::raw_ostream&amp;, llvm::raw_ostream&amp;, llvm::ArrayRef&lt;lld::DriverDef&gt;, bool) (/tmp/gecko/clang/bin/ld.lld+0xe9845)
#<!-- -->20 0x00005582acf70182 lld_main(int, char**, llvm::ToolContext const&amp;) (/tmp/gecko/clang/bin/ld.lld+0xe7182)
#<!-- -->21 0x00005582acf7004e main (/tmp/gecko/clang/bin/ld.lld+0xe704e)
#<!-- -->22 0x00007f765ab671ca __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3
#<!-- -->23 0x00007f765ab67285 call_init ./csu/../csu/libc-start.c:128:20
#<!-- -->24 0x00007f765ab67285 __libc_start_main ./csu/../csu/libc-start.c:347:5
#<!-- -->25 0x00005582acf71b72 _start (/tmp/gecko/clang/bin/ld.lld+0xe8b72)

Cc: @nikic

(It's also unfortunate that it doesn't tell what specific module is broken)

@nikic
Copy link
Contributor

nikic commented Oct 16, 2023

I've reverted the patch in a72d88f.

I've also reduced the issue to these two files:

llvm-link tmp/gecko/obj-x86_64-pc-linux-gnu/dom/media/platforms/ffmpeg/ffvpx/Unified_cpp_ffmpeg_ffvpx0.o tmp/gecko/obj-x86_64-pc-linux-gnu/dom/media/platforms/ffmpeg/libav53/Unified_cpp_ffmpeg_libav530.o

And then to the following reasonably minimal test case with the files at https://gist.github.com/nikic/ed40c6ddfaac1a3f32b9e8e4f862e9da:

llvm-link test1.ll test2.ll -S > test3.ll

The cause is pretty obvious now: We have a AVPacket types defined in both modules, but with incompatible definitions with different sizes -- presumably there is UB due to ODR violations involved here.

Linking then picks one of those, which is then incompatible with the alloca and verification complains.

Question to the debuginfo folks: What is the expected behavior in this case? Does that just mean verification is just fundamentally doomed due to possible ODR violations in debuginfo? Or should incompatible type definitions not be merged -- somehow, I have no idea if this is even possible?

alexfh referenced this issue Oct 16, 2023
…ragment size

Reapply now that generation of incorrect debuginfo for FnDef
in rustc has been fixed.

-----

Add a check that the DILocalVariable fragment size in dbg.declare
does not exceed the size of the alloca.

This would have caught the invalid debuginfo regenerated by rustc
in #64149.

Differential Revision: https://reviews.llvm.org/D158743
@dwblaikie
Copy link
Collaborator

Question to the debuginfo folks: What is the expected behavior in this case? Does that just mean verification is just fundamentally doomed due to possible ODR violations in debuginfo? Or should incompatible type definitions not be merged -- somehow, I have no idea if this is even possible?

@adrian-prantl @JDevlieghere @pogo59 - I /think/ historically we've let some of these things cause silent problems (like bad/weird debug info, but not a build/link break)), but hard breaks on ODR violations have been avoided?

Though I think we could go the other way, if the errors were more meaningful - like perhaps we could verify that merged types have the same size, if that's important (which it is)? But that has to happen during the merging - not sure if we have an option for "extra verification" during merging or not - maybe it's cheap enough to do all the time.

Such a failure should mention which input files the inconsistent definitions come from, their name, and probably/ideally, their source location (header file+line number). It's not perfect/not enough in some cases (eg: the same type, from the same header, but due to contextual preprocessor definitions or other compiler flags, the definitions come out with different sizes) but hopefully enough to make it actionable.

(total aside: Could be nice to have a "real" ODR checking of some kind - at least Google dropped ODR checking when we switched from GCC to Clang due to the two compilers having a different definition of where a class started (& the ODR checking in gold just checked the definitions came from the same file/line anyway, I think - or maybe it only did functions, now that I think about it... (since we used -gmlt for it))

@adrian-prantl
Copy link
Collaborator

I /think/ historically we've let some of these things cause silent problems (like bad/weird debug info, but not a build/link break)), but hard breaks on ODR violations have been avoided?

The compiler is allowed to assume that ODR violations don't happen and I don't think we ever went out of our way to provide any guarantees about the behavior if they do.

Could be nice to have a "real" ODR checking of some kind

You would have to, e.g., build a global DenseSet of all "name-addressed" types that is shared between all MetadataReaders and perform some form of checking (e.g., size, number of members, declcontext) there. I dont' know if we currently deserialize duplicate types from Bitcode, but if we do so already, it may not even be very expensive.

@glandium
Copy link
Contributor Author

presumably there is UB due to ODR violations involved here.

ODR doesn't apply to types in different compilation units, and presumably, there's no function calls between these that involve the duplicate but different type. Debug info should also be able to discriminate the types (and it does when you don't use LTO)

@dwblaikie
Copy link
Collaborator

presumably there is UB due to ODR violations involved here.

ODR doesn't apply to types in different compilation units,

I believe it applies to the whole program - all the code that's linked together.

To quote cppreference (in lieu of the actual spec, but it's pretty accurate):
https://en.cppreference.com/w/cpp/language/definition

There can be more than one definition in a program of each of the following: class type, ... as long as all of the following is true:

  • each definition appears in a different translation unit
  • each definition consists of the same sequence of tokens (typically, appears in the same header file)
  • name lookup from within each definition finds the same entities (after overload-resolution), except that
    constants with internal or no linkage may refer to different objects as long as they are not odr-used and have the same values in every definition

There's some other requirements, but those are the classic ones that are relevant here - certainly a type with a different number or size of members would be a violation of this part of the ODR.

and presumably, there's no function calls between these that involve the duplicate but different type.

Doesn't seem like a safe assumption to me. ODR violations can cause all sorts of quite silent problems/corruption/confusion. (but, yes, most of these ODR violations that survive into a code base for long probably are "safe"-ish - but it's still not valid C++ code)

Debug info should also be able to discriminate the types (and it does when you don't use LTO)

Incidentally, it doesn't discriminate even outside of LTO: with -fdebug-types-section, clang will emit DWARF type units and use a hash (technically a violation of the DWARF spec, which calls for structural hashing - which would be more like what you're describing) based on the same mangled name that we use for LTO type merging.

Essentially, LLVM's DWARF emission depends on the C++ ODR for both LTO and non-LTO (if you're using type units) and has done for a decade or so.

It's really important for type deduplication/size optimizations for DWARF - and it's faster to do it based on the name than doing a full structural comparison to decide whether they should be deduplicated.

But just checking the size would be enough to fail on the link/merge would probably be cheap enough to implement & diagnose at least some cases of ODR violations & not lead to downstream failures or excessive debug info/slower links/compiles.

@rgal
Copy link
Collaborator

rgal commented Oct 17, 2023

Tag @MaskRay who proposed an ODR checker approach in lld here: https://maskray.me/blog/2022-11-13-odr-violation-detection

@pogo59
Copy link
Collaborator

pogo59 commented Oct 20, 2023

I remember seeing licensee reports on this before (the fragment-size error) which we tracked down to, yes, ODR violation. Licensee fixed their code and we took a request for an ODR checker. We thought about doing something like having the IR linker do a structural-equivalence test, or at least a size check, when it sees debug-info types with the same (linkage) name. But it seems a bit expensive to do all the time?

@jmorse am I imagining that someone was toying with an ODR detector internally?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
debuginfo LTO Link time optimization (regular/full LTO or ThinLTO)
Projects
None yet
Development

No branches or pull requests

9 participants