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.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# 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]]
|
[[package]]
|
||||||
name = "make-initrd-ng"
|
name = "make-initrd-ng"
|
||||||
version = "0.1.0"
|
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
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
goblin = "0.5.0"
|
||||||
|
|
|
@ -3,11 +3,13 @@ use std::env;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::io::{BufRead, BufReader, Error, ErrorKind};
|
use std::io::{BufRead, BufReader, Error};
|
||||||
use std::os::unix;
|
use std::os::unix;
|
||||||
use std::path::{Component, Path, PathBuf};
|
use std::path::{Component, Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
|
use goblin::{elf::Elf, Object};
|
||||||
|
|
||||||
struct NonRepeatingQueue<T> {
|
struct NonRepeatingQueue<T> {
|
||||||
queue: VecDeque<T>,
|
queue: VecDeque<T>,
|
||||||
seen: HashSet<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> {
|
fn add_dependencies<P: AsRef<Path> + AsRef<OsStr>>(
|
||||||
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>>(
|
|
||||||
source: P,
|
source: P,
|
||||||
target: S,
|
elf: Elf,
|
||||||
queue: &mut NonRepeatingQueue<Box<Path>>,
|
queue: &mut NonRepeatingQueue<Box<Path>>,
|
||||||
) -> Result<(), Error> {
|
) {
|
||||||
fs::copy(&source, &target)?;
|
if let Some(interp) = elf.interpreter {
|
||||||
|
queue.push_back(Box::from(Path::new(interp)));
|
||||||
if !Command::new("ldd").arg(&source).output()?.status.success() {
|
|
||||||
// Not dynamically linked - no need to recurse
|
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let rpath_string = patch_elf("--print-rpath", &source)?;
|
let rpaths = if elf.runpaths.len() > 0 {
|
||||||
let needed_string = patch_elf("--print-needed", &source)?;
|
elf.runpaths
|
||||||
// Shared libraries don't have an interpreter
|
} else if elf.rpaths.len() > 0 {
|
||||||
if let Ok(interpreter_string) = patch_elf("--print-interpreter", &source) {
|
elf.rpaths
|
||||||
queue.push_back(Box::from(Path::new(&interpreter_string.trim())));
|
} else {
|
||||||
}
|
vec![]
|
||||||
|
};
|
||||||
|
|
||||||
let rpath = rpath_string
|
let rpaths_as_path = rpaths
|
||||||
.trim()
|
.into_iter()
|
||||||
.split(":")
|
.flat_map(|p| p.split(":"))
|
||||||
.map(|p| Box::<Path>::from(Path::new(p)))
|
.map(|p| Box::<Path>::from(Path::new(p)))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for line in needed_string.lines() {
|
for line in elf.libraries {
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
for path in &rpath {
|
for path in &rpaths_as_path {
|
||||||
let lib = path.join(line);
|
let lib = path.join(line);
|
||||||
if lib.exists() {
|
if lib.exists() {
|
||||||
// No need to recurse. The queue will bring it back round.
|
// 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
|
// Make file writable to strip it
|
||||||
let mut permissions = fs::metadata(&target)?.permissions();
|
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));
|
println!("{:?} was not successfully stripped.", OsStr::new(&target));
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue