|
@@ -1,10 +1,12 @@
|
|
use alloc::{
|
|
use alloc::{
|
|
boxed::Box,
|
|
boxed::Box,
|
|
collections::BTreeMap,
|
|
collections::BTreeMap,
|
|
|
|
+ rc::Rc,
|
|
string::{String, ToString},
|
|
string::{String, ToString},
|
|
vec::Vec,
|
|
vec::Vec,
|
|
};
|
|
};
|
|
use core::{
|
|
use core::{
|
|
|
|
+ cell::RefCell,
|
|
mem::{size_of, swap, transmute},
|
|
mem::{size_of, swap, transmute},
|
|
ptr, slice,
|
|
ptr, slice,
|
|
};
|
|
};
|
|
@@ -28,6 +30,7 @@ use crate::{
|
|
|
|
|
|
use super::{
|
|
use super::{
|
|
access::access,
|
|
access::access,
|
|
|
|
+ callbacks::LinkerCallbacks,
|
|
debug::{RTLDDebug, RTLDState, _dl_debug_state, _r_debug},
|
|
debug::{RTLDDebug, RTLDState, _dl_debug_state, _r_debug},
|
|
library::{DepTree, Library},
|
|
library::{DepTree, Library},
|
|
tcb::{Master, Tcb},
|
|
tcb::{Master, Tcb},
|
|
@@ -52,6 +55,9 @@ pub struct Linker {
|
|
root: Library,
|
|
root: Library,
|
|
verbose: bool,
|
|
verbose: bool,
|
|
tls_index_offset: usize,
|
|
tls_index_offset: usize,
|
|
|
|
+ lib_spaces: BTreeMap<usize, Library>,
|
|
|
|
+ counter: usize,
|
|
|
|
+ pub cbs: Rc<RefCell<LinkerCallbacks>>,
|
|
}
|
|
}
|
|
|
|
|
|
impl Linker {
|
|
impl Linker {
|
|
@@ -61,9 +67,11 @@ impl Linker {
|
|
root: Library::new(),
|
|
root: Library::new(),
|
|
verbose,
|
|
verbose,
|
|
tls_index_offset: 0,
|
|
tls_index_offset: 0,
|
|
|
|
+ lib_spaces: BTreeMap::new(),
|
|
|
|
+ counter: 1,
|
|
|
|
+ cbs: Rc::new(RefCell::new(LinkerCallbacks::new())),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
pub fn load(&mut self, name: &str, path: &str) -> Result<()> {
|
|
pub fn load(&mut self, name: &str, path: &str) -> Result<()> {
|
|
let mut lib: Library = Library::new();
|
|
let mut lib: Library = Library::new();
|
|
swap(&mut lib, &mut self.root);
|
|
swap(&mut lib, &mut self.root);
|
|
@@ -74,7 +82,13 @@ impl Linker {
|
|
}
|
|
}
|
|
return Ok(());
|
|
return Ok(());
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+ pub fn unload(&mut self, libspace: usize) {
|
|
|
|
+ if let Some(lib) = self.lib_spaces.remove(&libspace) {
|
|
|
|
+ for (_, mmap) in lib.mmaps {
|
|
|
|
+ unsafe { sys_mman::munmap(mmap.as_mut_ptr() as *mut c_void, mmap.len()) };
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
fn load_recursive(&mut self, name: &str, path: &str, lib: &mut Library) -> Result<DepTree> {
|
|
fn load_recursive(&mut self, name: &str, path: &str, lib: &mut Library) -> Result<DepTree> {
|
|
if self.verbose {
|
|
if self.verbose {
|
|
println!("load {}: {}", name, path);
|
|
println!("load {}: {}", name, path);
|
|
@@ -125,13 +139,16 @@ impl Linker {
|
|
return Ok(deps);
|
|
return Ok(deps);
|
|
}
|
|
}
|
|
|
|
|
|
- pub fn load_library(&mut self, name: &str) -> Result<Option<DepTree>> {
|
|
|
|
- // TODO this is wrong
|
|
|
|
|
|
+ pub fn load_library(&mut self, name: &str) -> Result<usize> {
|
|
let mut lib = Library::new();
|
|
let mut lib = Library::new();
|
|
- self._load_library(name, &mut lib)
|
|
|
|
|
|
+ self._load_library(name, &mut lib)?;
|
|
|
|
+ let ret = self.counter;
|
|
|
|
+ self.lib_spaces.insert(ret, lib);
|
|
|
|
+ self.counter += 1;
|
|
|
|
+ return Ok(ret);
|
|
}
|
|
}
|
|
fn _load_library(&mut self, name: &str, lib: &mut Library) -> Result<Option<DepTree>> {
|
|
fn _load_library(&mut self, name: &str, lib: &mut Library) -> Result<Option<DepTree>> {
|
|
- if lib.objects.contains_key(name) {
|
|
|
|
|
|
+ if lib.objects.contains_key(name) || self.root.objects.contains_key(name) {
|
|
// It should be previously resolved so we don't need to worry about it
|
|
// It should be previously resolved so we don't need to worry about it
|
|
Ok(None)
|
|
Ok(None)
|
|
} else if name.contains('/') {
|
|
} else if name.contains('/') {
|
|
@@ -212,9 +229,8 @@ impl Linker {
|
|
|
|
|
|
pub fn get_sym(&self, name: &str, libspace: Option<usize>) -> Option<usize> {
|
|
pub fn get_sym(&self, name: &str, libspace: Option<usize>) -> Option<usize> {
|
|
match libspace {
|
|
match libspace {
|
|
- Some(lib) => {
|
|
|
|
- //TODO this is the same kind of wrong
|
|
|
|
- let lib = Library::new();
|
|
|
|
|
|
+ Some(id) => {
|
|
|
|
+ let lib = self.lib_spaces.get(&id)?;
|
|
lib.get_sym(name)
|
|
lib.get_sym(name)
|
|
}
|
|
}
|
|
None => self.root.get_sym(name),
|
|
None => self.root.get_sym(name),
|
|
@@ -223,23 +239,18 @@ impl Linker {
|
|
|
|
|
|
pub fn run_init(&self, libspace: Option<usize>) -> Result<()> {
|
|
pub fn run_init(&self, libspace: Option<usize>) -> Result<()> {
|
|
match libspace {
|
|
match libspace {
|
|
- Some(lib) => {
|
|
|
|
- //TODO this is the same kind of wrong
|
|
|
|
- let lib = Library::new();
|
|
|
|
|
|
+ Some(id) => {
|
|
|
|
+ let lib = self.lib_spaces.get(&id).unwrap();
|
|
self.run_tree(&lib, &lib.dep_tree, ".init_array")
|
|
self.run_tree(&lib, &lib.dep_tree, ".init_array")
|
|
}
|
|
}
|
|
- None => {
|
|
|
|
- //TODO we first need to deinitialize all the loaded libraries first!
|
|
|
|
- self.run_tree(&self.root, &self.root.dep_tree, ".init_array")
|
|
|
|
- }
|
|
|
|
|
|
+ None => self.run_tree(&self.root, &self.root.dep_tree, ".init_array"),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
pub fn run_fini(&self, libspace: Option<usize>) -> Result<()> {
|
|
pub fn run_fini(&self, libspace: Option<usize>) -> Result<()> {
|
|
match libspace {
|
|
match libspace {
|
|
- Some(lib) => {
|
|
|
|
- //TODO this is the same kind of wrong
|
|
|
|
- let lib = Library::new();
|
|
|
|
|
|
+ Some(id) => {
|
|
|
|
+ let lib = self.lib_spaces.get(&id).unwrap().unwrap();
|
|
self.run_tree(&lib, &lib.dep_tree, ".fini_array")
|
|
self.run_tree(&lib, &lib.dep_tree, ".fini_array")
|
|
}
|
|
}
|
|
None => {
|
|
None => {
|
|
@@ -290,10 +301,11 @@ impl Linker {
|
|
libspace: Option<usize>,
|
|
libspace: Option<usize>,
|
|
) -> Result<Option<usize>> {
|
|
) -> Result<Option<usize>> {
|
|
match libspace {
|
|
match libspace {
|
|
- Some(lib) => {
|
|
|
|
- //TODO this is the same kind of wrong
|
|
|
|
- let mut lib = Library::new();
|
|
|
|
- self._link(primary_opt, dso, &mut lib)
|
|
|
|
|
|
+ Some(id) => {
|
|
|
|
+ let mut lib = self.lib_spaces.remove(&id).unwrap();
|
|
|
|
+ let res = self._link(primary_opt, dso, &mut lib);
|
|
|
|
+ self.lib_spaces.insert(id, lib);
|
|
|
|
+ res
|
|
}
|
|
}
|
|
None => {
|
|
None => {
|
|
let mut lib = Library::new();
|
|
let mut lib = Library::new();
|
|
@@ -317,7 +329,7 @@ impl Linker {
|
|
let mut elfs = BTreeMap::new();
|
|
let mut elfs = BTreeMap::new();
|
|
for (name, data) in lib.objects.iter() {
|
|
for (name, data) in lib.objects.iter() {
|
|
// Skip already linked libraries
|
|
// Skip already linked libraries
|
|
- if !lib.mmaps.contains_key(&*name) {
|
|
|
|
|
|
+ if !lib.mmaps.contains_key(&*name) && !self.root.mmaps.contains_key(&*name) {
|
|
elfs.insert(name.as_str(), Elf::parse(&data)?);
|
|
elfs.insert(name.as_str(), Elf::parse(&data)?);
|
|
}
|
|
}
|
|
}
|
|
}
|