message: Resolve Both strong and weak symbols
  This patch keep 2 lists, one for strong symbols and one for weak
  symbols. First it will check for the symbol to be resolved in the strong
  symbols' list, if it is not there it will then check in the weak symbol
  list.
diff: @@ -39,6 +39,8 @@ pub struct Linker {
  // 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]>,
  verbose: bool,
  @@ -51,6 +53,7 @@ impl Linker {
  library_path: library_path.to_string(),
  objects: BTreeMap::new(),
  globals: BTreeMap::new(),
  + weak_syms: BTreeMap::new(),
  mmaps: BTreeMap::new(),
  verbose,
  tls_index_offset: 0,
  @@ -129,21 +132,43 @@ impl Linker {
  }
  }
  - fn collect_syms(elf: &Elf, mmap: &[u8], verbose: bool) -> Result<BTreeMap<String, usize>> {
  + 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() {
  - if sym.st_bind() == sym::STB_GLOBAL && sym.st_value != 0 {
  + 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) {
  - let name = name_res?;
  - let value = mmap.as_ptr() as usize + sym.st_value as usize;
  + 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.to_string(), 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);
  + }
  + return Ok((globals, weak_syms));
  }
  pub fn get_sym(&self, name: &str) -> Option<usize> {
  @@ -152,6 +177,11 @@ impl Linker {
  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);
  @@ -252,8 +282,9 @@ impl Linker {
  if self.verbose {
  println!(" mmap {:p}, {:#x}", mmap.as_mut_ptr(), mmap.len());
  }
  - let globals = Linker::collect_syms(&elf, &mmap, self.verbose)?;
  + 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);
  }
  