Skip to content

Commit eafe82f

Browse files
committed
update
1 parent 54ec26e commit eafe82f

File tree

3 files changed

+74
-45
lines changed

3 files changed

+74
-45
lines changed

ci/run.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,7 @@ for rlib in "${rlib_paths[@]}"; do
172172
fi
173173
done
174174

175+
176+
cargo run -p symbol-check -- check-core-syms"${rlib_paths[@]}"
177+
175178
true

crates/symbol-check/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ edition = "2024"
55

66
[dependencies]
77
object = "0.36.7"
8+
9+
[features]
10+
wasm = ["object/wasm"]

crates/symbol-check/src/main.rs

Lines changed: 68 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,34 @@
1-
#![allow(unused)]
2-
3-
// use ar::Archive;
41
use object::read::archive::{ArchiveFile, ArchiveMember};
5-
use object::read::elf::FileHeader;
6-
use object::{Object, ObjectSection, ObjectSymbol, Symbol, SymbolKind, SymbolScope, SymbolSection};
7-
use std::collections::{BTreeMap, HashSet};
8-
use std::error::Error;
2+
use object::{Object, ObjectSymbol, Symbol, SymbolKind, SymbolScope, SymbolSection};
3+
use std::collections::{BTreeMap, BTreeSet};
94
use std::fs;
10-
use std::hash::Hash;
11-
use std::path::{Path, PathBuf};
12-
13-
type Result<T, E = Box<dyn Error>> = std::result::Result<T, E>;
5+
use std::path::Path;
146

157
const USAGE: &str = "Usage:
16-
symbol-check check-duplicates PATH...
17-
symbol-check check-core-syms PATH...
8+
9+
symbol-check check-duplicates PATHS...
10+
symbol-check check-core-syms PATHS...
1811
";
1912

2013
fn main() {
2114
let args = std::env::args().collect::<Vec<_>>();
22-
let args_ref = args.iter().map(|arg| arg.as_str()).collect::<Vec<_>>();
15+
let args_ref = args.iter().map(String::as_str).collect::<Vec<_>>();
2316

2417
match &args_ref[1..] {
2518
["check-duplicates", rest @ ..] if !rest.is_empty() => {
26-
rest.iter().for_each(verify_no_duplicates)
19+
rest.iter().for_each(verify_no_duplicates);
2720
}
2821
["check-core-syms", rest @ ..] if !rest.is_empty() => {
29-
rest.iter().for_each(verify_no_duplicates)
22+
rest.iter().for_each(verify_core_symbols);
3023
}
3124
_ => {
3225
println!("{USAGE}");
3326
std::process::exit(1);
3427
}
3528
}
36-
37-
// Raise an error if the same symbol is present in multiple object files
3829
}
3930

31+
#[expect(unused)] // only for printing
4032
#[derive(Clone, Debug)]
4133
struct SymInfo {
4234
name: String,
@@ -53,7 +45,7 @@ struct SymInfo {
5345
}
5446

5547
impl SymInfo {
56-
fn new(sym: Symbol, member: &ArchiveMember) -> Self {
48+
fn new(sym: &Symbol, member: &ArchiveMember) -> Self {
5749
Self {
5850
name: sym.name().expect("missing name").to_owned(),
5951
kind: sym.kind(),
@@ -70,56 +62,87 @@ impl SymInfo {
7062
}
7163
}
7264

65+
/// Ensure that the same global symbol isn't defined in multiple object files within an archive.
7366
fn verify_no_duplicates(path: impl AsRef<Path>) {
74-
println!("Checking for duplicates at {:?}", path.as_ref());
67+
println!("Checking for duplicates at {}", path.as_ref().display());
7568

76-
// Global defined symbols
7769
let mut syms = BTreeMap::<String, SymInfo>::new();
7870
let mut dups = Vec::new();
7971

8072
for_each_symbol(path, |sym, member| {
81-
if sym.is_global() && !sym.is_undefined() {
82-
let info = SymInfo::new(sym, member);
83-
match syms.get(&info.name) {
84-
Some(existing) => {
85-
dups.push(info);
86-
dups.push(existing.clone());
87-
}
88-
None => {
89-
syms.insert(info.name.clone(), info);
90-
}
73+
if !sym.is_global() || sym.is_undefined() {
74+
// Only check defined globals
75+
return;
76+
}
77+
78+
let info = SymInfo::new(&sym, member);
79+
match syms.get(&info.name) {
80+
Some(existing) => {
81+
dups.push(info);
82+
dups.push(existing.clone());
83+
}
84+
None => {
85+
syms.insert(info.name.clone(), info);
9186
}
9287
}
93-
Ok(())
94-
})
95-
.unwrap();
88+
});
89+
90+
if cfg!(windows) {
91+
let allowed_dup_pfx = ["__real@", "__xmm@"];
92+
dups.retain(|sym| !allowed_dup_pfx.iter().any(|pfx| sym.name.starts_with(pfx)));
93+
}
9694

9795
if !dups.is_empty() {
9896
dups.sort_unstable_by(|a, b| a.name.cmp(&b.name));
9997
panic!("Found duplicate symbols: {dups:#?}");
10098
}
99+
100+
println!("success: no duplicate symbols found");
101101
}
102102

103103
fn verify_core_symbols(path: impl AsRef<Path>) {
104-
todo!()
104+
println!(
105+
"Checking for references to core at {}",
106+
path.as_ref().display()
107+
);
108+
109+
let mut defined = BTreeSet::new();
110+
let mut undefined = Vec::new();
111+
112+
for_each_symbol(path, |sym, member| {
113+
if !sym.name().unwrap().contains("_ZN4core") {
114+
return;
115+
}
116+
117+
let info = SymInfo::new(&sym, member);
118+
if info.is_undefined {
119+
undefined.push(info);
120+
} else {
121+
defined.insert(info.name);
122+
}
123+
});
124+
125+
undefined.retain(|sym| !defined.contains(&sym.name));
126+
127+
if !undefined.is_empty() {
128+
undefined.sort_unstable_by(|a, b| a.name.cmp(&b.name));
129+
panic!("Found undefined symbols from `core`: {undefined:#?}");
130+
}
131+
132+
println!("success: no undefined references to core found");
105133
}
106134

107135
/// For a given archive path, do something with each symbol.
108-
fn for_each_symbol(
109-
path: impl AsRef<Path>,
110-
mut f: impl FnMut(Symbol, &ArchiveMember) -> Result<()>,
111-
) -> Result<()> {
112-
let archive_data = fs::read(path)?;
113-
let x = ArchiveFile::parse(archive_data.as_slice())?;
136+
fn for_each_symbol(path: impl AsRef<Path>, mut f: impl FnMut(Symbol, &ArchiveMember)) {
137+
let archive_data = fs::read(path).expect("reading file failed");
138+
let x = ArchiveFile::parse(archive_data.as_slice()).expect("archive parse failed");
114139
for member in x.members() {
115140
let member = member.unwrap();
116141
let data = member.data(&*archive_data).unwrap();
117-
let obj = object::File::parse(data)?;
142+
let obj = object::File::parse(data).expect("object parse failed");
118143

119144
for sym in obj.symbols() {
120-
f(sym, &member)?;
145+
f(sym, &member);
121146
}
122147
}
123-
124-
Ok(())
125148
}

0 commit comments

Comments
 (0)