Description
Compiling following under some circumstances result in undefined references to rust_oom
:
use std::alloc::{GlobalAlloc, System, Layout};
#[global_allocator]
static GLOBAL: Allocator = Allocator;
struct Allocator;
unsafe impl GlobalAlloc for Allocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
System.alloc(layout)
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
System.dealloc(ptr, layout)
}
}
fn main() {}
$ cargo -Zbuild-std test --target x86_64-unknown-linux-gnu
...
error: linking with `cc` failed: exit code: 1
|
= note: /usr/bin/ld: /.../target/x86_64-unknown-linux-gnu/debug/deps/liballoc-6e5029e924b1689e.rlib(alloc-6e5029e924b1689e.2h1lbzecyhyarcje.rcgu.o): in function `alloc::alloc::handle_alloc_error':
/.../.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/liballoc/alloc.rs:246: undefined reference to `rust_oom'
This linking issue occurs only under for some codegen partitioning but not the
others. Reproducing it requires controlling the options that influence the
number of codegen units. I can reproduce it with either incremental = true
,
or incremental = false
combined with codegen-units = 200
.
The weak lang items introduce cyclic dependencies between crates. For example,
the alloc crate depends on oom lang item which is defined in std. When linking
the std comes first, and it may so happen that object file that contains
rust_oom
definition is not used and omitted (this suggest why large number of
codegen units is necessary to reproduce the issue), and subsequently alloc
crate will fail to link.
The linking code tries to account for cyclic dependencies using
start-group and end-group, but as far as I can see it based on assumption that
weak lang items dependencies are always reversed, which no longer holds true.