Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a614590

Browse files
committed
symcheck: Support both archives and object files
If parsing as an archive is unsuccessful, try parsing as an object instead before erroring out.
1 parent 686dc87 commit a614590

File tree

1 file changed

+54
-28
lines changed

1 file changed

+54
-28
lines changed

‎crates/symbol-check/src/main.rs

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ use std::io::{BufRead, BufReader};
77
use std::path::{Path, PathBuf};
88
use std::process::{Command, Stdio};
99

10-
use object::read::archive::{ArchiveFile,ArchiveMember};
10+
use object::read::archive::ArchiveFile;
1111
use object::{
12-
File as ObjFile, Object, ObjectSection, ObjectSymbol, Symbol, SymbolKind, SymbolScope,
12+
File as ObjFile, Object, ObjectSection, ObjectSymbol, Result as ObjResult, Symbol, SymbolKind,
13+
SymbolScope,
1314
};
1415
use serde_json::Value;
1516

@@ -25,9 +26,10 @@ Cargo will get invoked with `CARGO_ARGS` and the specified target. All output
2526
2627
If TARGET is not specified, the host target is used.
2728
28-
check ARCHIVE_PATHS ...
29+
check PATHS ...
2930
30-
Run the same checks on the given set of paths, without invoking Cargo.
31+
Run the same checks on the given set of paths, without invoking Cargo. Paths
32+
may be either archives or object files.
3133
";
3234

3335
fn main() {
@@ -71,7 +73,7 @@ fn check_paths<P: AsRef<Path>>(paths: &[P]) {
7173
for path in paths {
7274
let path = path.as_ref();
7375
println!("Checking {}", path.display());
74-
let archive = Archive::from_path(path);
76+
let archive = BinFile::from_path(path);
7577

7678
verify_no_duplicates(&archive);
7779
verify_core_symbols(&archive);
@@ -174,7 +176,7 @@ struct SymInfo {
174176
}
175177

176178
impl SymInfo {
177-
fn new(sym: &Symbol, obj: &ObjFile, member: &ArchiveMember) -> Self {
179+
fn new(sym: &Symbol, obj: &ObjFile, obj_path: &str) -> Self {
178180
// Include the section name if possible. Fall back to the `Section` debug impl if not.
179181
let section = sym.section();
180182
let section_name = sym
@@ -196,7 +198,7 @@ impl SymInfo {
196198
is_weak: sym.is_weak(),
197199
is_common: sym.is_common(),
198200
address: sym.address(),
199-
object: String::from_utf8_lossy(member.name()).into_owned(),
201+
object: obj_path.to_owned(),
200202
}
201203
}
202204
}
@@ -206,7 +208,7 @@ impl SymInfo {
206208
/// Note that this will also locate cases where a symbol is weakly defined in more than one place.
207209
/// Technically there are no linker errors that will come from this, but it keeps our binary more
208210
/// straightforward and saves some distribution size.
209-
fn verify_no_duplicates(archive: &Archive) {
211+
fn verify_no_duplicates(archive: &BinFile) {
210212
let mut syms = BTreeMap::<String, SymInfo>::new();
211213
let mut dups = Vec::new();
212214
let mut found_any = false;
@@ -263,7 +265,7 @@ fn verify_no_duplicates(archive: &Archive) {
263265
}
264266

265267
/// Ensure that there are no references to symbols from `core` that aren't also (somehow) defined.
266-
fn verify_core_symbols(archive: &Archive) {
268+
fn verify_core_symbols(archive: &BinFile) {
267269
let mut defined = BTreeSet::new();
268270
let mut undefined = Vec::new();
269271
let mut has_symbols = false;
@@ -298,39 +300,63 @@ fn verify_core_symbols(archive: &Archive) {
298300
}
299301

300302
/// Thin wrapper for owning data used by `object`.
301-
struct Archive {
303+
struct BinFile {
304+
path: PathBuf,
302305
data: Vec<u8>,
303306
}
304307

305-
impl Archive {
308+
impl BinFile {
306309
fn from_path(path: &Path) -> Self {
307310
Self {
311+
path: path.to_owned(),
308312
data: fs::read(path).expect("reading file failed"),
309313
}
310314
}
311315

312-
fn file(&self) -> ArchiveFile<'_> {
313-
ArchiveFile::parse(self.data.as_slice()).expect("archive parse failed")
316+
fn as_archive_file(&self) -> ObjResult<ArchiveFile<'_>> {
317+
ArchiveFile::parse(self.data.as_slice())
314318
}
315319

316-
/// For a given archive, do something with each object file.
317-
fn for_each_object(&self, mut f: impl FnMut(ObjFile, &ArchiveMember)) {
318-
let archive = self.file();
319-
320-
for member in archive.members() {
321-
let member = member.expect("failed to access member");
322-
let obj_data = member
323-
.data(self.data.as_slice())
324-
.expect("failed to access object");
325-
let obj = ObjFile::parse(obj_data).expect("failed to parse object");
326-
f(obj, &member);
320+
fn as_obj_file(&self) -> ObjResult<ObjFile<'_>> {
321+
ObjFile::parse(self.data.as_slice())
322+
}
323+
324+
/// For a given archive, do something with each object file. For an object file, do
325+
/// something once.
326+
fn for_each_object(&self, mut f: impl FnMut(ObjFile, &str)) {
327+
// Try as an archive first.
328+
let as_archive = self.as_archive_file();
329+
if let Ok(archive) = as_archive {
330+
for member in archive.members() {
331+
let member = member.expect("failed to access member");
332+
let obj_data = member
333+
.data(self.data.as_slice())
334+
.expect("failed to access object");
335+
let obj = ObjFile::parse(obj_data).expect("failed to parse object");
336+
f(obj, &String::from_utf8_lossy(member.name()));
337+
}
338+
339+
return;
327340
}
341+
342+
// Fall back to parsing as an object file.
343+
let as_obj = self.as_obj_file();
344+
if let Ok(obj) = as_obj {
345+
f(obj, &self.path.to_string_lossy());
346+
return;
347+
}
348+
349+
panic!(
350+
"failed to parse as either archive or object file: {:?}, {:?}",
351+
as_archive.unwrap_err(),
352+
as_obj.unwrap_err(),
353+
);
328354
}
329355

330-
/// For a given archive, do something with each symbol.
331-
fn for_each_symbol(&self, mut f: impl FnMut(Symbol, &ObjFile, &ArchiveMember)) {
332-
self.for_each_object(|obj, member| {
333-
obj.symbols().for_each(|sym| f(sym, &obj, member));
356+
/// D something with each symbol in an archive or object file.
357+
fn for_each_symbol(&self, mut f: impl FnMut(Symbol, &ObjFile, &str)) {
358+
self.for_each_object(|obj, obj_path| {
359+
obj.symbols().for_each(|sym| f(sym, &obj, obj_path));
334360
});
335361
}
336362
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /