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

Separate library specific data from main Linker struct

parent aaf017d9
No related branches found
No related tags found
No related merge requests found
use alloc::{
boxed::Box,
collections::{BTreeMap, BTreeSet},
string::String,
vec::Vec,
};
#[derive(Default, Debug)]
pub struct DepTree {
pub name: String,
pub deps: Vec<DepTree>,
}
impl DepTree {
pub fn new(name: String) -> DepTree {
DepTree {
name,
deps: Vec::new(),
}
}
}
/// Use to represnt a library as well as all th symbols that is loaded withen it.
#[derive(Default)]
pub struct Library {
/// Global symbols
pub globals: BTreeMap<String, usize>,
/// Weak symbols
pub weak_syms: BTreeMap<String, usize>,
/// Loaded library raw data
pub objects: BTreeMap<String, Box<[u8]>>,
/// Loaded library in-memory data
pub mmaps: BTreeMap<String, &'static mut [u8]>,
/// Each object will have its children called once with no repetition.
pub dep_tree: DepTree,
/// A set used to detect circular dependencies in the Linker::load function
pub cir_dep: BTreeSet<String>,
}
impl Library {
pub fn new() -> Library {
Default::default()
}
pub fn get_sym(&self, name: &str) -> Option<usize> {
if let Some(value) = self.globals.get(name) {
Some(*value)
} else if let Some(value) = self.weak_syms.get(name) {
Some(*value)
} else {
None
}
}
}
use alloc::{
boxed::Box,
collections::{BTreeMap, BTreeSet},
collections::BTreeMap,
string::{String, ToString},
vec::Vec,
};
......@@ -29,6 +29,7 @@ use crate::{
use super::{
access::access,
debug::{RTLDDebug, RTLDState, _dl_debug_state, _r_debug},
library::{DepTree, Library},
tcb::{Master, Tcb},
PAGE_SIZE,
};
......@@ -43,61 +44,30 @@ pub struct DSO {
pub base_addr: usize,
pub entry_point: usize,
}
#[derive(Default, Debug)]
pub struct DepTree {
pub name: String,
pub deps: Vec<DepTree>,
}
impl DepTree {
fn new(name: String) -> DepTree {
DepTree {
name,
deps: Vec::new(),
}
}
}
pub struct Linker {
// Used by load
/// Library path to search when loading library by name
library_path: String,
/// Loaded library raw data
objects: BTreeMap<String, Box<[u8]>>,
// Used by link
/// Global symbols
globals: BTreeMap<String, usize>,
/// Weak symbols
weak_syms: BTreeMap<String, usize>,
/// Loaded library in-memory data
mmaps: BTreeMap<String, &'static mut [u8]>,
root: Library,
verbose: bool,
tls_index_offset: usize,
/// A set used to detect circular dependencies in the Linker::load function
cir_dep: BTreeSet<String>,
/// Each object will have its children callec once with no repetition.
dep_tree: DepTree,
}
impl Linker {
pub fn new(library_path: &str, verbose: bool) -> Self {
Self {
library_path: library_path.to_string(),
objects: BTreeMap::new(),
globals: BTreeMap::new(),
weak_syms: BTreeMap::new(),
mmaps: BTreeMap::new(),
root: Library::new(),
verbose,
tls_index_offset: 0,
cir_dep: BTreeSet::new(),
dep_tree: Default::default(),
}
}
pub fn load(&mut self, name: &str, path: &str) -> Result<()> {
self.dep_tree = self.load_recursive(name, path)?;
self.root.dep_tree = self.load_recursive(name, path)?;
if self.verbose {
println!("Dep tree: {:#?}", self.dep_tree);
println!("Dep tree: {:#?}", self.root.dep_tree);
}
return Ok(());
}
......@@ -106,7 +76,7 @@ impl Linker {
if self.verbose {
println!("load {}: {}", name, path);
}
if self.cir_dep.contains(name) {
if self.root.cir_dep.contains(name) {
return Err(Error::Malformed(format!(
"Circular dependency: {} is a dependency of itself",
name
......@@ -115,7 +85,7 @@ impl Linker {
let mut deps = DepTree::new(name.to_string());
let mut data = Vec::new();
self.cir_dep.insert(name.to_string());
self.root.cir_dep.insert(name.to_string());
let path_c = CString::new(path)
.map_err(|err| Error::Malformed(format!("invalid path '{}': {}", path, err)))?;
......@@ -128,7 +98,7 @@ impl Linker {
.map_err(|err| Error::Malformed(format!("failed to read '{}': {}", path, err)))?;
}
deps.deps = self.load_data(name, data.into_boxed_slice())?;
self.cir_dep.remove(name);
self.root.cir_dep.remove(name);
Ok(deps)
}
......@@ -142,13 +112,13 @@ impl Linker {
}
}
self.objects.insert(name.to_string(), data);
self.root.objects.insert(name.to_string(), data);
return Ok(deps);
}
pub fn load_library(&mut self, name: &str) -> Result<Option<DepTree>> {
if self.objects.contains_key(name) {
if self.root.objects.contains_key(name) {
// It should be previously resolved so we don't need to worry about it
Ok(None)
} else if name.contains('/') {
......@@ -228,25 +198,10 @@ impl Linker {
}
pub fn get_sym(&self, name: &str) -> Option<usize> {
if let Some(value) = self.globals.get(name) {
if self.verbose {
println!(" sym {} = {:#x}", name, value);
}
Some(*value)
} else if let Some(value) = self.weak_syms.get(name) {
if self.verbose {
println!(" sym {} = {:#x}", name, value);
}
Some(*value)
} else {
if self.verbose {
println!(" sym {} = undefined", name);
}
None
}
self.root.get_sym(name)
}
pub fn run_init(&self) -> Result<()> {
self.run_init_tree(&self.dep_tree)
self.run_init_tree(&self.root.dep_tree)
}
fn run_init_tree(&self, root: &DepTree) -> Result<()> {
......@@ -256,11 +211,11 @@ impl Linker {
if self.verbose {
println!("init {}", &root.name);
}
let mmap = match self.mmaps.get(&root.name) {
let mmap = match self.root.mmaps.get(&root.name) {
Some(some) => some,
None => return Ok(()),
};
let elf = Elf::parse(self.objects.get(&root.name).unwrap())?;
let elf = Elf::parse(self.root.objects.get(&root.name).unwrap())?;
for section in &elf.section_headers {
let name = match elf.shdr_strtab.get(section.sh_name) {
Some(x) => match x {
......@@ -284,18 +239,18 @@ impl Linker {
}
pub fn run_fini(&self) -> Result<()> {
self.run_fini_tree(&self.dep_tree)
self.run_fini_tree(&self.root.dep_tree)
}
fn run_fini_tree(&self, root: &DepTree) -> Result<()> {
if self.verbose {
println!("init {}", &root.name);
}
let mmap = match self.mmaps.get(&root.name) {
let mmap = match self.root.mmaps.get(&root.name) {
Some(some) => some,
None => return Ok(()),
};
let elf = Elf::parse(self.objects.get(&root.name).unwrap())?;
let elf = Elf::parse(self.root.objects.get(&root.name).unwrap())?;
for section in &elf.section_headers {
let name = match elf.shdr_strtab.get(section.sh_name) {
Some(x) => match x {
......@@ -326,9 +281,9 @@ impl Linker {
_dl_debug_state();
let elfs = {
let mut elfs = BTreeMap::new();
for (name, data) in self.objects.iter() {
for (name, data) in self.root.objects.iter() {
// Skip already linked libraries
if !self.mmaps.contains_key(&*name) {
if !self.root.mmaps.contains_key(&*name) {
elfs.insert(name.as_str(), Elf::parse(&data)?);
}
}
......@@ -342,7 +297,7 @@ impl Linker {
if self.verbose {
println!("map {}", elf_name);
}
let object = match self.objects.get(*elf_name) {
let object = match self.root.objects.get(*elf_name) {
Some(some) => some,
None => continue,
};
......@@ -478,9 +433,9 @@ impl Linker {
println!(" mmap {:p}, {:#x}", mmap.as_mut_ptr(), mmap.len());
}
let (globals, weak_syms) = Linker::collect_syms(&elf, &mmap, self.verbose)?;
self.globals.extend(globals.into_iter());
self.weak_syms.extend(weak_syms.into_iter());
self.mmaps.insert(elf_name.to_string(), mmap);
self.root.globals.extend(globals.into_iter());
self.root.weak_syms.extend(weak_syms.into_iter());
self.root.mmaps.insert(elf_name.to_string(), mmap);
}
// Allocate TLS
......@@ -515,12 +470,12 @@ impl Linker {
if same_elf {
continue;
}
let object = match self.objects.get(*elf_name) {
let object = match self.root.objects.get(*elf_name) {
Some(some) => some,
None => continue,
};
let mmap = match self.mmaps.get_mut(*elf_name) {
let mmap = match self.root.mmaps.get_mut(*elf_name) {
Some(some) => some,
None => continue,
};
......@@ -660,7 +615,7 @@ impl Linker {
let a = rel.r_addend.unwrap_or(0) as usize;
let mmap = match self.mmaps.get_mut(*elf_name) {
let mmap = match self.root.mmaps.get_mut(*elf_name) {
Some(some) => some,
None => continue,
};
......@@ -741,7 +696,7 @@ impl Linker {
}
if let Some(dyn_start_addr) = dyn_start {
if let Some(i) = debug_start {
let mmap = match self.mmaps.get_mut(*elf_name) {
let mmap = match self.root.mmaps.get_mut(*elf_name) {
Some(some) => some,
None => continue,
};
......@@ -778,7 +733,7 @@ impl Linker {
prot |= sys_mman::PROT_WRITE;
}
let mmap = match self.mmaps.get_mut(*elf_name) {
let mmap = match self.root.mmaps.get_mut(*elf_name) {
Some(some) => some,
None => continue,
};
......@@ -811,7 +766,7 @@ impl Linker {
// Perform indirect relocations (necessary evil), gather entry point
let mut entry_opt = None;
for (elf_name, elf) in elfs.iter() {
let mmap = match self.mmaps.get_mut(*elf_name) {
let mmap = match self.root.mmaps.get_mut(*elf_name) {
Some(some) => some,
None => continue,
};
......
......@@ -6,6 +6,7 @@ pub const PAGE_SIZE: usize = 4096;
mod access;
pub mod debug;
mod library;
pub mod linker;
pub mod start;
pub mod tcb;
......
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