Add support for RUNPATH
This commit is contained in:
@@ -36,6 +36,7 @@ pub struct Library {
|
||||
pub dep_tree: DepTree,
|
||||
/// A set used to detect circular dependencies in the Linker::load function
|
||||
pub cir_dep: BTreeSet<String>,
|
||||
pub runpath: Option<String>,
|
||||
}
|
||||
impl Library {
|
||||
pub fn new() -> Library {
|
||||
|
||||
+33
-7
@@ -14,7 +14,7 @@ use goblin::{
|
||||
elf::{
|
||||
header::ET_DYN,
|
||||
program_header,
|
||||
r#dyn::{Dyn, DT_DEBUG},
|
||||
r#dyn::{Dyn, DT_DEBUG, DT_RUNPATH},
|
||||
reloc, sym, Elf,
|
||||
},
|
||||
error::{Error, Result},
|
||||
@@ -63,7 +63,8 @@ impl Symbol {
|
||||
pub struct Linker {
|
||||
// Used by load
|
||||
/// Library path to search when loading library by name
|
||||
library_path: String,
|
||||
default_library_path: String,
|
||||
ld_library_path: Option<String>,
|
||||
root: Library,
|
||||
verbose: bool,
|
||||
tls_index_offset: usize,
|
||||
@@ -73,9 +74,10 @@ pub struct Linker {
|
||||
}
|
||||
|
||||
impl Linker {
|
||||
pub fn new(library_path: &str, verbose: bool) -> Self {
|
||||
pub fn new(ld_library_path: Option<String>, verbose: bool) -> Self {
|
||||
Self {
|
||||
library_path: library_path.to_string(),
|
||||
default_library_path: "/lib".to_string(),
|
||||
ld_library_path: ld_library_path,
|
||||
root: Library::new(),
|
||||
verbose,
|
||||
tls_index_offset: 0,
|
||||
@@ -139,13 +141,30 @@ impl Linker {
|
||||
) -> Result<Vec<DepTree>> {
|
||||
let elf = Elf::parse(&data)?;
|
||||
//println!("{:#?}", elf);
|
||||
|
||||
// search for RUNPATH
|
||||
lib.runpath = if let Some(dynamic) = elf.dynamic {
|
||||
let entry = dynamic.dyns.iter().find(|d| d.d_tag == DT_RUNPATH);
|
||||
match entry {
|
||||
Some(entry) => {
|
||||
let path = elf
|
||||
.dynstrtab
|
||||
.get(entry.d_val as usize)
|
||||
.ok_or(Error::Malformed("Missing RUNPATH in dynstrtab".to_string()))??;
|
||||
Some(path.to_string())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut deps = Vec::new();
|
||||
for library in elf.libraries.iter() {
|
||||
if let Some(dep) = self._load_library(library, lib)? {
|
||||
deps.push(dep);
|
||||
}
|
||||
}
|
||||
let elf = Elf::parse(&data)?;
|
||||
let key = match elf.soname {
|
||||
Some(soname) => soname,
|
||||
_ => name,
|
||||
@@ -171,8 +190,15 @@ impl Linker {
|
||||
} else if name.contains('/') {
|
||||
Ok(Some(self.load_recursive(name, name, lib)?))
|
||||
} else {
|
||||
let library_path = self.library_path.clone();
|
||||
for part in library_path.split(PATH_SEP) {
|
||||
let mut paths = Vec::new();
|
||||
if let Some(ld_library_path) = &self.ld_library_path {
|
||||
paths.push(ld_library_path);
|
||||
}
|
||||
if let Some(runpath) = &lib.runpath {
|
||||
paths.push(runpath);
|
||||
}
|
||||
paths.push(&self.default_library_path);
|
||||
for part in paths.iter() {
|
||||
let path = if part.is_empty() {
|
||||
format!("./{}", name)
|
||||
} else {
|
||||
|
||||
+2
-5
@@ -183,10 +183,7 @@ pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) ->
|
||||
}
|
||||
|
||||
// Some variables that will be overridden by environment and auxiliary vectors
|
||||
let library_path = match envs.get("LD_LIBRARY_PATH") {
|
||||
Some(lib_path) => lib_path.to_owned() + ":/lib",
|
||||
None => "/lib".to_owned(),
|
||||
};
|
||||
let ld_library_path = envs.get("LD_LIBRARY_PATH").map(|s| s.to_owned());
|
||||
|
||||
let name_or_path = if is_manual {
|
||||
// ld.so is run directly by user and not via execve() or similar systemcall
|
||||
@@ -234,7 +231,7 @@ pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) ->
|
||||
}
|
||||
pr
|
||||
};
|
||||
let mut linker = Linker::new(&library_path, false);
|
||||
let mut linker = Linker::new(ld_library_path, false);
|
||||
match linker.load(&path, &path) {
|
||||
Ok(()) => (),
|
||||
Err(err) => {
|
||||
|
||||
Reference in New Issue
Block a user