From 4860ab12fa7120b35a36fec33b16fd6624f5d549 Mon Sep 17 00:00:00 2001
From: oddcoder <ahmedsoliman@oddcoder.com>
Date: Sat, 7 Mar 2020 23:56:08 +0200
Subject: [PATCH] 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.
---
 src/ld_so/linker.rs | 47 +++++++++++++++++++++++++++++++++++++--------
 1 file changed, 39 insertions(+), 8 deletions(-)

diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs
index fe98fae5f..848645146 100644
--- a/src/ld_so/linker.rs
+++ b/src/ld_so/linker.rs
@@ -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 {
-                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;
+            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.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);
         }
 
-- 
GitLab