about summary refs log tree commit diff
path: root/pkgs/build-support/kernel
diff options
context:
space:
mode:
authorK900 <me@0upti.me>2022-07-30 12:31:15 +0300
committerK900 <me@0upti.me>2022-08-02 10:19:48 +0300
commitdaee67dae658c4a060cda0ff885c87e3ca28c5ae (patch)
treecea8bd64c72f836741dd9bb4aa948f8417abe434 /pkgs/build-support/kernel
parent1356441cb15f623442dee51e3bb7d66f85eadcde (diff)
make-initrd-ng: use goblin instead of shelling out to patchelf and friends
Diffstat (limited to 'pkgs/build-support/kernel')
-rw-r--r--pkgs/build-support/kernel/make-initrd-ng/Cargo.lock92
-rw-r--r--pkgs/build-support/kernel/make-initrd-ng/Cargo.toml1
-rw-r--r--pkgs/build-support/kernel/make-initrd-ng/src/main.rs100
3 files changed, 142 insertions, 51 deletions
diff --git a/pkgs/build-support/kernel/make-initrd-ng/Cargo.lock b/pkgs/build-support/kernel/make-initrd-ng/Cargo.lock
index 75e732029b511..cce94b3f4cfb9 100644
--- a/pkgs/build-support/kernel/make-initrd-ng/Cargo.lock
+++ b/pkgs/build-support/kernel/make-initrd-ng/Cargo.lock
@@ -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"
diff --git a/pkgs/build-support/kernel/make-initrd-ng/Cargo.toml b/pkgs/build-support/kernel/make-initrd-ng/Cargo.toml
index 9076f6b156176..c30eccd9fec72 100644
--- a/pkgs/build-support/kernel/make-initrd-ng/Cargo.toml
+++ b/pkgs/build-support/kernel/make-initrd-ng/Cargo.toml
@@ -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"
diff --git a/pkgs/build-support/kernel/make-initrd-ng/src/main.rs b/pkgs/build-support/kernel/make-initrd-ng/src/main.rs
index 32830ff4e7953..de1e3ee724a6c 100644
--- a/pkgs/build-support/kernel/make-initrd-ng/src/main.rs
+++ b/pkgs/build-support/kernel/make-initrd-ng/src/main.rs
@@ -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,22 +84,36 @@ fn copy_file<P: AsRef<Path> + AsRef<OsStr>, S: AsRef<Path> + AsRef<OsStr>>(
             );
         }
     }
+}
 
-    // Make file writable to strip it
-    let mut permissions = fs::metadata(&target)?.permissions();
-    permissions.set_readonly(false);
-    fs::set_permissions(&target, permissions)?;
-
-    // Strip further than normal
-    if !Command::new("strip")
-        .arg("--strip-all")
-        .arg(OsStr::new(&target))
-        .output()?
-        .status
-        .success()
-    {
-        println!("{:?} was not successfully stripped.", OsStr::new(&target));
-    }
+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();
+        permissions.set_readonly(false);
+        fs::set_permissions(&target, permissions)?;
+
+        // Strip further than normal
+        if !Command::new("strip")
+            .arg("--strip-all")
+            .arg(OsStr::new(&target))
+            .output()?
+            .status
+            .success()
+        {
+            println!("{:?} was not successfully stripped.", OsStr::new(&target));
+        }
+    };
 
     Ok(())
 }