Skip to content
Snippets Groups Projects
Commit cc7ff54d authored by Ahmed Abd El Mawgood's avatar Ahmed Abd El Mawgood
Browse files

Catch circular dependency when resolving loading shared libraries

This patch implements tree-based data-structure for catching circular
dependency where libA.so will depen on arbitrarily long chain (including
zero length) of libNs.so one of which will depend on libA.so again. The
main intention of this patch was merely capturing the dependency tree to
prioterize which Elf's .init_array and which .fini_array should run
first, but as a side effect it can capture circular dependencies as well.
parent 7724989b
No related branches found
No related tags found
1 merge request!265Init fini ld.so
use alloc::{ use alloc::{
boxed::Box, boxed::Box,
collections::BTreeMap, collections::{BTreeMap, BTreeSet},
string::{String, ToString}, string::{String, ToString},
vec::Vec, vec::Vec,
}; };
...@@ -59,6 +59,8 @@ pub struct Linker { ...@@ -59,6 +59,8 @@ pub struct Linker {
mmaps: BTreeMap<String, &'static mut [u8]>, mmaps: BTreeMap<String, &'static mut [u8]>,
verbose: bool, verbose: bool,
tls_index_offset: usize, tls_index_offset: usize,
// used to detect circular dependencies in the Linker::load function
cir_dep: BTreeSet<String>,
} }
impl Linker { impl Linker {
...@@ -71,6 +73,7 @@ impl Linker { ...@@ -71,6 +73,7 @@ impl Linker {
mmaps: BTreeMap::new(), mmaps: BTreeMap::new(),
verbose, verbose,
tls_index_offset: 0, tls_index_offset: 0,
cir_dep: BTreeSet::new(),
} }
} }
...@@ -78,6 +81,14 @@ impl Linker { ...@@ -78,6 +81,14 @@ impl Linker {
if self.verbose { if self.verbose {
println!("load {}: {}", name, path); println!("load {}: {}", name, path);
} }
if self.cir_dep.contains(name) {
return Err(Error::Malformed(format!(
"Circular dependency: {} is a dependency of itself",
name
)));
}
self.cir_dep.insert(name.to_string());
let mut data = Vec::new(); let mut data = Vec::new();
let path_c = CString::new(path) let path_c = CString::new(path)
...@@ -91,19 +102,17 @@ impl Linker { ...@@ -91,19 +102,17 @@ impl Linker {
file.read_to_end(&mut data) file.read_to_end(&mut data)
.map_err(|err| Error::Malformed(format!("failed to read '{}': {}", path, err)))?; .map_err(|err| Error::Malformed(format!("failed to read '{}': {}", path, err)))?;
} }
let result = self.load_data(name, data.into_boxed_slice());
self.load_data(name, data.into_boxed_slice()) self.cir_dep.remove(name);
result
} }
pub fn load_data(&mut self, name: &str, data: Box<[u8]>) -> Result<()> { pub fn load_data(&mut self, name: &str, data: Box<[u8]>) -> Result<()> {
//TODO: Prevent failures due to recursion let elf = Elf::parse(&data)?;
{ //println!("{:#?}", elf);
let elf = Elf::parse(&data)?;
//println!("{:#?}", elf);
for library in elf.libraries.iter() { for library in elf.libraries.iter() {
self.load_library(library)?; self.load_library(library)?;
}
} }
self.objects.insert(name.to_string(), data); self.objects.insert(name.to_string(), data);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment