|
@@ -38,7 +38,9 @@ pub struct Linker {
|
|
|
|
|
|
// Used by link
|
|
// Used by link
|
|
/// Global symbols
|
|
/// Global symbols
|
|
- pub globals: BTreeMap<String, usize>,
|
|
|
|
|
|
+ globals: BTreeMap<String, usize>,
|
|
|
|
+ /// Weak symbols
|
|
|
|
+ weak_syms: BTreeMap<String, usize>,
|
|
/// Loaded library in-memory data
|
|
/// Loaded library in-memory data
|
|
mmaps: BTreeMap<String, &'static mut [u8]>,
|
|
mmaps: BTreeMap<String, &'static mut [u8]>,
|
|
verbose: bool,
|
|
verbose: bool,
|
|
@@ -51,6 +53,7 @@ impl Linker {
|
|
library_path: library_path.to_string(),
|
|
library_path: library_path.to_string(),
|
|
objects: BTreeMap::new(),
|
|
objects: BTreeMap::new(),
|
|
globals: BTreeMap::new(),
|
|
globals: BTreeMap::new(),
|
|
|
|
+ weak_syms: BTreeMap::new(),
|
|
mmaps: BTreeMap::new(),
|
|
mmaps: BTreeMap::new(),
|
|
verbose,
|
|
verbose,
|
|
tls_index_offset: 0,
|
|
tls_index_offset: 0,
|
|
@@ -129,6 +132,64 @@ impl Linker {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ fn collect_syms(
|
|
|
|
+ elf: &Elf,
|
|
|
|
+ mmap: &[u8],
|
|
|
|
+ verbose: bool,
|
|
|
|
+ ) -> Result<(BTreeMap<String, usize>, BTreeMap<String, usize>)> {
|
|
|
|
+ let mut globals = BTreeMap::new();
|
|
|
|
+ let mut weak_syms = BTreeMap::new();
|
|
|
|
+ for sym in elf.dynsyms.iter() {
|
|
|
|
+ let bind = sym.st_bind();
|
|
|
|
+ if sym.st_value == 0 || ![sym::STB_GLOBAL, sym::STB_WEAK].contains(&bind) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ let name: String;
|
|
|
|
+ let value: usize;
|
|
|
|
+ if let Some(name_res) = elf.dynstrtab.get(sym.st_name) {
|
|
|
|
+ name = name_res?.to_string();
|
|
|
|
+ value = mmap.as_ptr() as usize + sym.st_value as usize;
|
|
|
|
+ } else {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ match sym.st_bind() {
|
|
|
|
+ sym::STB_GLOBAL => {
|
|
|
|
+ if verbose {
|
|
|
|
+ println!(" global {}: {:x?} = {:#x}", &name, sym, value);
|
|
|
|
+ }
|
|
|
|
+ globals.insert(name, value);
|
|
|
|
+ }
|
|
|
|
+ sym::STB_WEAK => {
|
|
|
|
+ if verbose {
|
|
|
|
+ println!(" weak {}: {:x?} = {:#x}", &name, sym, value);
|
|
|
|
+ }
|
|
|
|
+ weak_syms.insert(name, value);
|
|
|
|
+ }
|
|
|
|
+ _ => unreachable!(),
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return Ok((globals, weak_syms));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 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
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
pub fn link(&mut self, primary_opt: Option<&str>) -> Result<Option<usize>> {
|
|
pub fn link(&mut self, primary_opt: Option<&str>) -> Result<Option<usize>> {
|
|
let elfs = {
|
|
let elfs = {
|
|
let mut elfs = BTreeMap::new();
|
|
let mut elfs = BTreeMap::new();
|
|
@@ -179,7 +240,7 @@ impl Linker {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
program_header::PT_TLS => {
|
|
program_header::PT_TLS => {
|
|
- if self.verbose{
|
|
|
|
|
|
+ if self.verbose {
|
|
println!(" load tls {:#x}: {:x?}", vsize, ph);
|
|
println!(" load tls {:#x}: {:x?}", vsize, ph);
|
|
}
|
|
}
|
|
tls_size += vsize;
|
|
tls_size += vsize;
|
|
@@ -221,18 +282,9 @@ impl Linker {
|
|
if self.verbose {
|
|
if self.verbose {
|
|
println!(" mmap {:p}, {:#x}", mmap.as_mut_ptr(), mmap.len());
|
|
println!(" mmap {:p}, {:#x}", mmap.as_mut_ptr(), mmap.len());
|
|
}
|
|
}
|
|
- // Locate all globals
|
|
|
|
- for sym in elf.dynsyms.iter() {
|
|
|
|
- if sym.st_bind() == sym::STB_GLOBAL && sym.st_value != 0 {
|
|
|
|
- if let Some(name_res) = elf.dynstrtab.get(sym.st_name) {
|
|
|
|
- let name = name_res?;
|
|
|
|
- let value = mmap.as_ptr() as usize + sym.st_value as usize;
|
|
|
|
- // println!(" global {}: {:x?} = {:#x}", name, sym, value);
|
|
|
|
- self.globals.insert(name.to_string(), value);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+ 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.mmaps.insert(elf_name.to_string(), mmap);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -242,7 +294,7 @@ impl Linker {
|
|
} else {
|
|
} else {
|
|
None
|
|
None
|
|
};
|
|
};
|
|
- if self.verbose{
|
|
|
|
|
|
+ if self.verbose {
|
|
println!("tcb {:x?}", tcb_opt);
|
|
println!("tcb {:x?}", tcb_opt);
|
|
}
|
|
}
|
|
// Copy data
|
|
// Copy data
|
|
@@ -331,14 +383,20 @@ impl Linker {
|
|
);
|
|
);
|
|
}
|
|
}
|
|
if Some(*elf_name) == primary_opt {
|
|
if Some(*elf_name) == primary_opt {
|
|
- tls_ranges.insert(elf_name.to_string(), (self.tls_index_offset, tcb_master.range()));
|
|
|
|
|
|
+ tls_ranges.insert(
|
|
|
|
+ elf_name.to_string(),
|
|
|
|
+ (self.tls_index_offset, tcb_master.range()),
|
|
|
|
+ );
|
|
tcb_masters[0] = tcb_master;
|
|
tcb_masters[0] = tcb_master;
|
|
} else {
|
|
} else {
|
|
tcb_master.offset -= tls_offset;
|
|
tcb_master.offset -= tls_offset;
|
|
tls_offset += vsize;
|
|
tls_offset += vsize;
|
|
tls_ranges.insert(
|
|
tls_ranges.insert(
|
|
elf_name.to_string(),
|
|
elf_name.to_string(),
|
|
- (self.tls_index_offset + tcb_masters.len(), tcb_master.range()),
|
|
|
|
|
|
+ (
|
|
|
|
+ self.tls_index_offset + tcb_masters.len(),
|
|
|
|
+ tcb_master.range(),
|
|
|
|
+ ),
|
|
);
|
|
);
|
|
tcb_masters.push(tcb_master);
|
|
tcb_masters.push(tcb_master);
|
|
}
|
|
}
|
|
@@ -360,10 +418,6 @@ impl Linker {
|
|
|
|
|
|
// Perform relocations, and protect pages
|
|
// Perform relocations, and protect pages
|
|
for (elf_name, elf) in elfs.iter() {
|
|
for (elf_name, elf) in elfs.iter() {
|
|
- let mmap = match self.mmaps.get_mut(*elf_name) {
|
|
|
|
- Some(some) => some,
|
|
|
|
- None => continue,
|
|
|
|
- };
|
|
|
|
if self.verbose {
|
|
if self.verbose {
|
|
println!("link {}", elf_name);
|
|
println!("link {}", elf_name);
|
|
}
|
|
}
|
|
@@ -379,10 +433,6 @@ impl Linker {
|
|
// rel
|
|
// rel
|
|
// );
|
|
// );
|
|
|
|
|
|
- let a = rel.r_addend.unwrap_or(0) as usize;
|
|
|
|
-
|
|
|
|
- let b = mmap.as_mut_ptr() as usize;
|
|
|
|
-
|
|
|
|
let s = if rel.r_sym > 0 {
|
|
let s = if rel.r_sym > 0 {
|
|
let sym = elf.dynsyms.get(rel.r_sym).ok_or(Error::Malformed(format!(
|
|
let sym = elf.dynsyms.get(rel.r_sym).ok_or(Error::Malformed(format!(
|
|
"missing symbol for relocation {:?}",
|
|
"missing symbol for relocation {:?}",
|
|
@@ -396,18 +446,20 @@ impl Linker {
|
|
"missing name for symbol {:?}",
|
|
"missing name for symbol {:?}",
|
|
sym
|
|
sym
|
|
)))??;
|
|
)))??;
|
|
-
|
|
|
|
- if let Some(value) = self.globals.get(name) {
|
|
|
|
- // println!(" sym {}: {:x?} = {:#x}", name, sym, value);
|
|
|
|
- *value
|
|
|
|
- } else {
|
|
|
|
- // println!(" sym {}: {:x?} = undefined", name, sym);
|
|
|
|
- 0
|
|
|
|
- }
|
|
|
|
|
|
+ self.get_sym(name).unwrap_or(0)
|
|
} else {
|
|
} else {
|
|
0
|
|
0
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ let a = rel.r_addend.unwrap_or(0) as usize;
|
|
|
|
+
|
|
|
|
+ let mmap = match self.mmaps.get_mut(*elf_name) {
|
|
|
|
+ Some(some) => some,
|
|
|
|
+ None => continue,
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ let b = mmap.as_mut_ptr() as usize;
|
|
|
|
+
|
|
let (tm, t) = if let Some((tls_index, tls_range)) = tls_ranges.get(*elf_name) {
|
|
let (tm, t) = if let Some((tls_index, tls_range)) = tls_ranges.get(*elf_name) {
|
|
(*tls_index, tls_range.start)
|
|
(*tls_index, tls_range.start)
|
|
} else {
|
|
} else {
|
|
@@ -473,6 +525,10 @@ impl Linker {
|
|
prot |= sys_mman::PROT_WRITE;
|
|
prot |= sys_mman::PROT_WRITE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ let mmap = match self.mmaps.get_mut(*elf_name) {
|
|
|
|
+ Some(some) => some,
|
|
|
|
+ None => continue,
|
|
|
|
+ };
|
|
let res = unsafe {
|
|
let res = unsafe {
|
|
let ptr = mmap.as_mut_ptr().add(vaddr);
|
|
let ptr = mmap.as_mut_ptr().add(vaddr);
|
|
if self.verbose {
|
|
if self.verbose {
|