diff --git a/Cargo.lock b/Cargo.lock index 770afa7bae..c4b6eb587d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1898,6 +1898,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b6c2ebff6180198788f5db08d7ce3bc1d0b617176678831a7510825973e357" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.5.6" @@ -3312,6 +3321,7 @@ version = "0.1.0" dependencies = [ "bumpalo", "clap 3.0.0-beta.1", + "memmap2 0.3.1", "object 0.26.0", ] @@ -3798,7 +3808,7 @@ dependencies = [ "dlib 0.4.2", "lazy_static", "log", - "memmap2", + "memmap2 0.1.0", "nix 0.18.0", "wayland-client", "wayland-cursor", diff --git a/linker/Cargo.toml b/linker/Cargo.toml index 40444f77ec..4608e87f67 100644 --- a/linker/Cargo.toml +++ b/linker/Cargo.toml @@ -18,7 +18,8 @@ test = false bench = false [dependencies] +bumpalo = { version = "3.6.1", features = ["collections"] } # TODO switch to clap 3.0.0 once it's out. Tried adding clap = "~3.0.0-beta.1" and cargo wouldn't accept it clap = { git = "https://github.com/rtfeldman/clap", branch = "master" } -object = { version = "0.26", features = ["read"] } -bumpalo = { version = "3.6.1", features = ["collections"] } \ No newline at end of file +memmap2 = "0.3" +object = { version = "0.26", features = ["read"] } \ No newline at end of file diff --git a/linker/src/lib.rs b/linker/src/lib.rs index 05313d0ae1..40757fb96c 100644 --- a/linker/src/lib.rs +++ b/linker/src/lib.rs @@ -1,4 +1,7 @@ -use clap::{App, AppSettings, Arg}; +use clap::{App, AppSettings, Arg, ArgMatches}; +use memmap2::Mmap; +use object::Object; +use std::fs; use std::io; pub const CMD_PREPROCESS: &str = "preprocess"; @@ -29,6 +32,46 @@ pub fn build_app<'a>() -> App<'a> { ) } -pub fn preprocess() -> io::Result<()> { - panic!("sad"); +pub fn preprocess(matches: &ArgMatches) -> io::Result { + let _app_functions = application_functions(&matches.value_of(SHARED_LIB).unwrap())?; + + let exec_file = fs::File::open(&matches.value_of(EXEC).unwrap())?; + let exec_mmap = unsafe { Mmap::map(&exec_file)? }; + let exec_obj = object::File::parse(&*exec_mmap).map_err(|err| { + io::Error::new( + io::ErrorKind::InvalidData, + format!("Failed to parse executable file: {}", err), + ) + })?; + + // TODO: Extract PLT related information for these functions. + // TODO: For all text sections check for function calls to app functions. + // TODO: Store all this data in a nice format. + // TODO: Potentially create a version of the executable with certain dynamic and PLT information deleted. + // It may be fine to just add some of this information to the metadata instead and deal with it on final exec creation. + + Ok(0) +} + +fn application_functions(shared_lib_name: &str) -> io::Result> { + let shared_file = fs::File::open(&shared_lib_name)?; + let shared_mmap = unsafe { Mmap::map(&shared_file)? }; + let shared_obj = object::File::parse(&*shared_mmap).map_err(|err| { + io::Error::new( + io::ErrorKind::InvalidData, + format!("Failed to parse shared library file: {}", err), + ) + })?; + shared_obj + .exports() + .unwrap() + .into_iter() + .map(|export| String::from_utf8(export.name().to_vec())) + .collect::, _>>() + .map_err(|err| { + io::Error::new( + io::ErrorKind::InvalidData, + format!("Failed to load function names from shared library: {}", err), + ) + }) } diff --git a/linker/src/main.rs b/linker/src/main.rs index 494d46c39b..92a2be48fa 100644 --- a/linker/src/main.rs +++ b/linker/src/main.rs @@ -7,8 +7,8 @@ fn main() -> io::Result<()> { let exit_code = match matches.subcommand_name() { None => Ok::(-1), Some(CMD_PREPROCESS) => { - preprocess()?; - Ok(0) + let sub_matches = matches.subcommand_matches(CMD_PREPROCESS).unwrap(); + preprocess(sub_matches) } Some(CMD_SURGERY) => Ok(0), _ => unreachable!(),