Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 85db3ab

Browse files
committedMar 3, 2025
Add test for -znostart-stop-gc in LLD
1 parent 09e2387 commit 85db3ab

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#![crate_type = "rlib"]
2+
3+
// This file contains a very minimalistic reproduction of what the
4+
// linkme (https://github.com/dtolnay/linkme) crate does.
5+
// This linker behavior fails with LLD without -znostart-stop-gc.
6+
7+
type Item = fn(u32);
8+
9+
pub struct DistributedSlice {
10+
section_start: *const Item,
11+
section_stop: *const Item,
12+
}
13+
14+
unsafe impl Sync for DistributedSlice {}
15+
16+
impl DistributedSlice {
17+
pub fn get_slice(&self) -> &'static [Item] {
18+
let stride = std::mem::size_of::<Item>();
19+
let start = self.section_start;
20+
let stop = self.section_stop;
21+
let byte_offset = stop as usize - start as usize;
22+
let len = byte_offset / stride;
23+
unsafe { std::slice::from_raw_parts(start, len) }
24+
}
25+
}
26+
27+
pub static EXTERN_FNS: DistributedSlice = {
28+
unsafe extern "Rust" {
29+
// The __start_ and __stop_ section names are magical for the linker,
30+
// It will put link sections named EXTERNFNS in-between them.
31+
#[link_name = "__start_EXTERNFNS"]
32+
static SECTION_START: Item;
33+
#[link_name = "__stop_EXTERNFNS"]
34+
static SECTION_STOP: Item;
35+
}
36+
DistributedSlice {
37+
section_start: &raw const SECTION_START,
38+
section_stop: &raw const SECTION_STOP
39+
}
40+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
extern crate dep;
2+
3+
use dep::EXTERN_FNS;
4+
5+
// Add a function to the distributed slice contained in
6+
// the EXTERNFNS link section.
7+
#[used]
8+
#[unsafe(link_section = "EXTERNFNS")]
9+
pub static EXTERN_FN_LOCAL: fn(u32) = extern_fn;
10+
11+
fn extern_fn(x: u32) {
12+
println!("{x}");
13+
}
14+
15+
fn main() {
16+
for func in EXTERN_FNS.get_slice() {
17+
func(42);
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// This test checks that when certain link sections are not garbage
2+
// collected by LLD. The compiler needs to use the -znostart-stop-gc flag for LLD,
3+
// otherwise this test will fail.
4+
// The test replicates the behavior of the linkme crate.
5+
//
6+
//@ needs-rust-lld
7+
//@ only-x86_64-unknown-linux-gnu
8+
9+
use run_make_support::{run, rustc};
10+
11+
fn main() {
12+
rustc().input("dep.rs").run();
13+
rustc().input("foo.rs").run();
14+
15+
run("foo").assert_stdout_equals("42\n");
16+
}

0 commit comments

Comments
 (0)
Failed to load comments.