Skip to main content

max / makenotwork

2.4 KB · 67 lines History Blame Raw
1 /// Cross-check the in-house ELF read against binutils on whatever binaries this
2 /// machine happens to have. Not a unit test of the parser (those live beside it);
3 /// a differential against the tool everyone else would have used.
4 #[test]
5 fn compare_against_readelf() {
6 // Skip where binutils is not installed rather than failing: this is a
7 // differential, and with nothing to differ against there is nothing to say.
8 if std::process::Command::new("readelf")
9 .arg("--version")
10 .output()
11 .is_err()
12 {
13 eprintln!("no readelf on this machine; skipping the differential");
14 return;
15 }
16 let mut checked = 0;
17 let candidates: Vec<String> = std::fs::read_dir("/usr/bin")
18 .into_iter()
19 .flatten()
20 .flatten()
21 .map(|e| e.path().to_string_lossy().into_owned())
22 .take(400)
23 .collect();
24 for p in candidates {
25 let Ok(bytes) = std::fs::read(&p) else {
26 continue;
27 };
28 if bytes.len() < 64 || &bytes[..4] != b"\x7fELF" {
29 continue;
30 }
31 let mine = sando_daemon::elf::glibc_floor(&bytes).map(|v| v.to_string());
32 let Ok(out) = std::process::Command::new("readelf")
33 .args(["-V", &p])
34 .output()
35 else {
36 continue;
37 };
38 if !out.status.success() {
39 continue;
40 }
41 let s = String::from_utf8_lossy(&out.stdout);
42 // Only the version-requirement section; readelf -V also prints defined
43 // versions, which are not what a floor is made of.
44 let req = match s.split_once("Version needs section") {
45 Some((_, rest)) => rest,
46 None => "",
47 };
48 let mut best: Option<(u32, u32)> = None;
49 for tok in req.split(|c: char| !(c.is_alphanumeric() || c == '.' || c == '_')) {
50 if let Some(v) = tok.strip_prefix("GLIBC_")
51 && let Some((a, b)) = v.split_once('.')
52 && let (Ok(a), Ok(b)) = (a.parse::<u32>(), b.parse::<u32>())
53 {
54 best = Some(best.map_or((a, b), |x| x.max((a, b))));
55 }
56 }
57 let theirs = best.map(|(a, b)| format!("{a}.{b}"));
58 assert_eq!(mine, theirs, "disagreed on {p}");
59 checked += 1;
60 }
61 println!("agreed with readelf on {checked} binaries");
62 assert!(
63 checked > 20,
64 "only {checked} binaries compared; too few to mean anything"
65 );
66 }
67