make-initrd-ng: use goblin instead of shelling out to patchelf and friends
This commit is contained in:
parent
1356441cb1
commit
daee67dae6
3 changed files with 141 additions and 50 deletions
92
pkgs/build-support/kernel/make-initrd-ng/Cargo.lock
generated
92
pkgs/build-support/kernel/make-initrd-ng/Cargo.lock
generated
|
@ -1,5 +1,97 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "goblin"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91766b1121940d622933a13e20665857648681816089c9bc2075c4b75a6e4f6b"
|
||||
dependencies = [
|
||||
"log",
|
||||
"plain",
|
||||
"scroll",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "make-initrd-ng"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"goblin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plain"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scroll"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da"
|
||||
dependencies = [
|
||||
"scroll_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scroll_derive"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bdbda6ac5cd1321e724fa9cee216f3a61885889b896f073b8f82322789c5250e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
|
||||
|
|
|
@ -7,3 +7,4 @@ edition = "2018"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
goblin = "0.5.0"
|
||||
|
|
|
@ -3,11 +3,13 @@ use std::env;
|
|||
use std::ffi::OsStr;
|
||||
use std::fs;
|
||||
use std::hash::Hash;
|
||||
use std::io::{BufRead, BufReader, Error, ErrorKind};
|
||||
use std::io::{BufRead, BufReader, Error};
|
||||
use std::os::unix;
|
||||
use std::path::{Component, Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use goblin::{elf::Elf, Object};
|
||||
|
||||
struct NonRepeatingQueue<T> {
|
||||
queue: VecDeque<T>,
|
||||
seen: HashSet<T>,
|
||||
|
@ -38,50 +40,32 @@ impl<T: Clone + Eq + Hash> NonRepeatingQueue<T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn patch_elf<S: AsRef<OsStr>, P: AsRef<OsStr>>(mode: S, path: P) -> Result<String, Error> {
|
||||
let output = Command::new("patchelf").arg(&mode).arg(&path).output()?;
|
||||
if output.status.success() {
|
||||
Ok(String::from_utf8(output.stdout).expect("Failed to parse output"))
|
||||
} else {
|
||||
Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
format!(
|
||||
"failed: patchelf {:?} {:?}",
|
||||
OsStr::new(&mode),
|
||||
OsStr::new(&path)
|
||||
),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn copy_file<P: AsRef<Path> + AsRef<OsStr>, S: AsRef<Path> + AsRef<OsStr>>(
|
||||
fn add_dependencies<P: AsRef<Path> + AsRef<OsStr>>(
|
||||
source: P,
|
||||
target: S,
|
||||
elf: Elf,
|
||||
queue: &mut NonRepeatingQueue<Box<Path>>,
|
||||
) -> Result<(), Error> {
|
||||
fs::copy(&source, &target)?;
|
||||
|
||||
if !Command::new("ldd").arg(&source).output()?.status.success() {
|
||||
// Not dynamically linked - no need to recurse
|
||||
return Ok(());
|
||||
) {
|
||||
if let Some(interp) = elf.interpreter {
|
||||
queue.push_back(Box::from(Path::new(interp)));
|
||||
}
|
||||
|
||||
let rpath_string = patch_elf("--print-rpath", &source)?;
|
||||
let needed_string = patch_elf("--print-needed", &source)?;
|
||||
// Shared libraries don't have an interpreter
|
||||
if let Ok(interpreter_string) = patch_elf("--print-interpreter", &source) {
|
||||
queue.push_back(Box::from(Path::new(&interpreter_string.trim())));
|
||||
}
|
||||
let rpaths = if elf.runpaths.len() > 0 {
|
||||
elf.runpaths
|
||||
} else if elf.rpaths.len() > 0 {
|
||||
elf.rpaths
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let rpath = rpath_string
|
||||
.trim()
|
||||
.split(":")
|
||||
let rpaths_as_path = rpaths
|
||||
.into_iter()
|
||||
.flat_map(|p| p.split(":"))
|
||||
.map(|p| Box::<Path>::from(Path::new(p)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for line in needed_string.lines() {
|
||||
for line in elf.libraries {
|
||||
let mut found = false;
|
||||
for path in &rpath {
|
||||
for path in &rpaths_as_path {
|
||||
let lib = path.join(line);
|
||||
if lib.exists() {
|
||||
// No need to recurse. The queue will bring it back round.
|
||||
|
@ -100,6 +84,19 @@ fn copy_file<P: AsRef<Path> + AsRef<OsStr>, S: AsRef<Path> + AsRef<OsStr>>(
|
|||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn copy_file<P: AsRef<Path> + AsRef<OsStr>, S: AsRef<Path> + AsRef<OsStr>>(
|
||||
source: P,
|
||||
target: S,
|
||||
queue: &mut NonRepeatingQueue<Box<Path>>,
|
||||
) -> Result<(), Error> {
|
||||
fs::copy(&source, &target)?;
|
||||
|
||||
let contents = fs::read(&source)?;
|
||||
|
||||
if let Ok(Object::Elf(e)) = Object::parse(&contents) {
|
||||
add_dependencies(source, e, queue);
|
||||
|
||||
// Make file writable to strip it
|
||||
let mut permissions = fs::metadata(&target)?.permissions();
|
||||
|
@ -116,6 +113,7 @@ fn copy_file<P: AsRef<Path> + AsRef<OsStr>, S: AsRef<Path> + AsRef<OsStr>>(
|
|||
{
|
||||
println!("{:?} was not successfully stripped.", OsStr::new(&target));
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue