Skip to content

Commit f6562a3

Browse files
committed
tests: add test for symbol length
`__pinned_init` or `__init` functions are natural inline boundaries. Things within them calling into helper functions should be inlined, and wrapping functions that forwarding call to them should be, too. But these functions themselves can contain complex initialization, so it's best to leave it to the compilers to decide if they're inlineable. As a result, these symbols do show up in the symbol table when they're not inlined. Linux kernel has 512 byte symbol length limit, so we need to keep them small. Add a test to ensure that any growth of them are being considered and not accidental. Signed-off-by: Gary Guo <gary@garyguo.net>
1 parent 7f07d24 commit f6562a3

1 file changed

Lines changed: 61 additions & 0 deletions

File tree

tests/symbol_length.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#![cfg(all(unix, not(miri)))]
2+
3+
use std::io::{Error, Result, Write};
4+
5+
use pin_init::*;
6+
7+
#[pin_data]
8+
pub struct Test {}
9+
10+
pub fn init() -> impl PinInit<Test, Error> {
11+
pin_init!(Test {} ? Error)
12+
}
13+
14+
fn init_fn_ptr<T, E, I: PinInit<T, E>>(_: &I) -> *mut () {
15+
I::__pinned_init as *mut ()
16+
}
17+
18+
fn read_symbols() -> Result<Vec<String>> {
19+
let path = std::env::current_exe()?;
20+
let output = std::process::Command::new("nm")
21+
.arg(path)
22+
.arg("--just-symbols")
23+
.output()?;
24+
if !output.status.success() {
25+
Err(Error::other("exit code is not 0"))?
26+
}
27+
let symbols = String::from_utf8_lossy(&output.stdout);
28+
Ok(symbols
29+
.lines()
30+
.filter(|x| !x.is_empty())
31+
.map(|x| x.to_owned())
32+
.collect())
33+
}
34+
35+
#[test]
36+
fn type_name() {
37+
let init = init();
38+
let init_fn = init_fn_ptr(&init);
39+
std::hint::black_box(init_fn);
40+
41+
let mut symbols = match read_symbols() {
42+
Ok(v) => v,
43+
Err(err) => {
44+
// This might be some setup issue (e.g. no nm installed).
45+
// Instead of failing the test, print the error and continue.
46+
// Do not use `eprintln!()` as it would be captured.
47+
writeln!(std::io::stderr(), "cannot read symbols {:?}", err).unwrap();
48+
return;
49+
}
50+
};
51+
52+
// Filter out non-related symbols.
53+
symbols.retain(|x| x.contains("pin_init") && !x.contains("map"));
54+
55+
// Find the longest symbol
56+
symbols.sort_by_key(|x| x.len().wrapping_neg());
57+
let symbol = &symbols[0];
58+
println!("{}: {}", symbol.len(), symbol);
59+
60+
assert!(symbol.len() < 180);
61+
}

0 commit comments

Comments
 (0)