|
@@ -14,7 +14,7 @@ use goblin::{
|
|
elf::{
|
|
elf::{
|
|
header::ET_DYN,
|
|
header::ET_DYN,
|
|
program_header,
|
|
program_header,
|
|
- r#dyn::{Dyn, DT_DEBUG},
|
|
|
|
|
|
+ r#dyn::{Dyn, DT_DEBUG, DT_RUNPATH},
|
|
reloc, sym, Elf,
|
|
reloc, sym, Elf,
|
|
},
|
|
},
|
|
error::{Error, Result},
|
|
error::{Error, Result},
|
|
@@ -63,7 +63,8 @@ impl Symbol {
|
|
pub struct Linker {
|
|
pub struct Linker {
|
|
// Used by load
|
|
// Used by load
|
|
/// Library path to search when loading library by name
|
|
/// Library path to search when loading library by name
|
|
- library_path: String,
|
|
|
|
|
|
+ default_library_path: String,
|
|
|
|
+ ld_library_path: Option<String>,
|
|
root: Library,
|
|
root: Library,
|
|
verbose: bool,
|
|
verbose: bool,
|
|
tls_index_offset: usize,
|
|
tls_index_offset: usize,
|
|
@@ -73,9 +74,10 @@ pub struct Linker {
|
|
}
|
|
}
|
|
|
|
|
|
impl Linker {
|
|
impl Linker {
|
|
- pub fn new(library_path: &str, verbose: bool) -> Self {
|
|
|
|
|
|
+ pub fn new(ld_library_path: Option<String>, verbose: bool) -> Self {
|
|
Self {
|
|
Self {
|
|
- library_path: library_path.to_string(),
|
|
|
|
|
|
+ default_library_path: "/lib".to_string(),
|
|
|
|
+ ld_library_path: ld_library_path,
|
|
root: Library::new(),
|
|
root: Library::new(),
|
|
verbose,
|
|
verbose,
|
|
tls_index_offset: 0,
|
|
tls_index_offset: 0,
|
|
@@ -139,13 +141,30 @@ impl Linker {
|
|
) -> Result<Vec<DepTree>> {
|
|
) -> Result<Vec<DepTree>> {
|
|
let elf = Elf::parse(&data)?;
|
|
let elf = Elf::parse(&data)?;
|
|
//println!("{:#?}", elf);
|
|
//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();
|
|
let mut deps = Vec::new();
|
|
for library in elf.libraries.iter() {
|
|
for library in elf.libraries.iter() {
|
|
if let Some(dep) = self._load_library(library, lib)? {
|
|
if let Some(dep) = self._load_library(library, lib)? {
|
|
deps.push(dep);
|
|
deps.push(dep);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- let elf = Elf::parse(&data)?;
|
|
|
|
let key = match elf.soname {
|
|
let key = match elf.soname {
|
|
Some(soname) => soname,
|
|
Some(soname) => soname,
|
|
_ => name,
|
|
_ => name,
|
|
@@ -171,8 +190,15 @@ impl Linker {
|
|
} else if name.contains('/') {
|
|
} else if name.contains('/') {
|
|
Ok(Some(self.load_recursive(name, name, lib)?))
|
|
Ok(Some(self.load_recursive(name, name, lib)?))
|
|
} else {
|
|
} 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() {
|
|
let path = if part.is_empty() {
|
|
format!("./{}", name)
|
|
format!("./{}", name)
|
|
} else {
|
|
} else {
|