use crate::check_shlibs::{CheckShlibs, CheckState};
use crate::check_shlibs::{check_pkg, check_shlib};
use goblin::elf::Elf;
use std::path::{Path, PathBuf};
impl CheckShlibs {
pub fn check_dso(
&self,
path: &Path,
object: &[u8],
state: &mut CheckState,
) -> anyhow::Result<()> {
let elf = match Elf::parse(object) {
Ok(o) => o,
Err(_) => return Ok(()),
};
let mut rpaths: Vec<String> = vec![];
if let Some(p) = elf.runpaths.first() {
rpaths.extend(p.split(':').map(|s| s.to_string()));
}
if let Some(p) = elf.rpaths.first() {
rpaths.extend(p.split(':').map(|s| s.to_string()));
}
'nextlib: for lib in elf.libraries {
for rpath in &rpaths {
let mut libpath = state.destdir.clone();
let rp = PathBuf::from(rpath);
match rp.strip_prefix("/") {
Ok(p) => libpath.push(p),
Err(_) => libpath.push(rp),
}
libpath.push(lib);
let exists = match state.statlibs.get(&libpath) {
Some(e) => *e,
None => {
let e = libpath.exists();
state.statlibs.insert(libpath.to_path_buf(), e);
e
}
};
if exists {
continue 'nextlib;
}
}
for rpath in &rpaths {
let mut libpath: PathBuf;
match &state.cross_destdir {
Some(crossdir) => {
libpath = PathBuf::from(crossdir);
match rpath.strip_prefix('/') {
Some(p) => libpath.push(p),
None => libpath.push(rpath),
}
}
None => libpath = PathBuf::from(rpath),
};
libpath.push(lib);
let exists = match state.statlibs.get(&libpath) {
Some(e) => *e,
None => {
let e = libpath.exists();
state.statlibs.insert(libpath.to_path_buf(), e);
e
}
};
if exists {
check_shlib(path, &libpath, state);
check_pkg(path, &libpath, state)?;
continue 'nextlib;
}
}
for rpath in &state.system_paths {
let mut libpath = PathBuf::from(rpath);
libpath.push(lib);
let exists = match state.statlibs.get(&libpath) {
Some(e) => *e,
None => {
let e = libpath.exists();
state.statlibs.insert(libpath.to_path_buf(), e);
e
}
};
if exists {
check_shlib(path, &libpath, state);
continue 'nextlib;
}
}
println!("{}: missing library: {}", path.display(), lib);
}
Ok(())
}
}