Skip to content

Passing -lto-embed-bitcode=optimized to the lld gives a corrupted .llvmbc section. #84395

Open
@vext01

Description

@vext01

Hi everyone,

(This issue is based on this SO post)

libLTO has the option to embed the post-merged-and-optimised (i.e. final) bitcode into the end binary. This is done with the -lto-embed-bitcode=optimized option to lld.

Example of the use of this option with clang:

$ clang  -fuse-ld=lld -flto -Wl,--plugin-opt=-lto-embed-bitcode=optimized world.c
$ objcopy a.out --dump-section .llvmbc=llvm.bc
$ llvm-dis llvm.bc
$ head -5 llvm.ll
; ModuleID = 'llvm.bc'
source_filename = "ld-temp.o"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

Equivalent in the Rust world:

$ RUSTFLAGS="-C linker_plugin_lto -C linker=clang -C link-arg=-fuse-ld=lld -C link-arg=-Wl,--plugin-opt=-lto-embed-bitcode=optimized" cargo build --release
   Compiling world v0.1.0 (/tmp/world)
    Finished release [optimized] target(s) in 0.21s
$ objcopy target/release/world --dump-section .llvmbc=llvm.bc
$ llvm-dis llvm.bc
LLVM ERROR: Invalid encoding
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.
Stack dump:
0.      Program arguments: llvm-dis llvm.bc
 #0 0x000055ef6668578c llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/vext01/research/yorick/llvm-project/inst/bin/llvm-dis+0x1b578c)
 #1 0x000055ef666836e4 llvm::sys::RunSignalHandlers() (/home/vext01/research/yorick/llvm-project/inst/bin/llvm-dis+0x1b36e4)
 #2 0x000055ef66683843 SignalHandler(int) (/home/vext01/research/yorick/llvm-project/inst/bin/llvm-dis+0x1b3843)
 #3 0x00007fbcf1776730 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x12730)
 #4 0x00007fbcf105c7bb raise /build/glibc-vjB4T1/glibc-2.28/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #5 0x00007fbcf1047535 abort /build/glibc-vjB4T1/glibc-2.28/stdlib/abort.c:81:7
 #6 0x000055ef6665a753 llvm::report_fatal_error(llvm::Twine const&, bool) (/home/vext01/research/yorick/llvm-project/inst/bin/llvm-dis+0x18a753)
 #7 0x000055ef6665a868 (/home/vext01/research/yorick/llvm-project/inst/bin/llvm-dis+0x18a868)
 #8 0x000055ef66692703 llvm::BitstreamCursor::ReadAbbrevRecord() (/home/vext01/research/yorick/llvm-project/inst/bin/llvm-dis+0x1c2703)
 #9 0x000055ef6652149d llvm::BitstreamCursor::advance(unsigned int) (.constprop.1679) (/home/vext01/research/yorick/llvm-project/inst/bin/llvm-dis+0x5149d)
#10 0x000055ef6652fabd llvm::getBitcodeFileContents(llvm::MemoryBufferRef) (/home/vext01/research/yorick/llvm-project/inst/bin/llvm-dis+0x5fabd)
#11 0x000055ef66515159 main (/home/vext01/research/yorick/llvm-project/inst/bin/llvm-dis+0x45159)
#12 0x00007fbcf104909b __libc_start_main /build/glibc-vjB4T1/glibc-2.28/csu/../csu/libc-start.c:342:3
#13 0x000055ef6651a6ea _start (/home/vext01/research/yorick/llvm-project/inst/bin/llvm-dis+0x4a6ea)
Aborted

If I search the dumped section for the bitcode magic header bytes, 0x4243c0de, there are lots of hits. If I add -C codegen-units=1 to RUSTFLAGS then there are then fewer hits (exactly two).

It looks to me (although I can't be sure) like rustc is invoking the linker in such a way that the .llvmbc sections of the intermediate objects are not being discarded post-LTO, but instead being concatenated back to back (as linkers do) with the .llvmbc section of the post-LTO bitcode. So .llvmbc would contain many modules, but it should contain only the post-LTO bitcode module.

Assuming this is the case, this is problematic: it's not trivial to split the concatenated bitstreams apart (the magic bytes cannot be used as a reliable delimiter, as those bytes may appear in other unrelated contexts), and even if we could, we wouldn't know which of the resulting modules was the post-LTO one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-linkageArea: linking into static, shared libraries and binariesC-bugCategory: This is a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions