From 7b29f6eb27fbba311ea659ce0be1ecaa83d7557f Mon Sep 17 00:00:00 2001
From: oddcoder <ahmedsoliman@oddcoder.com>
Date: Mon, 10 Aug 2020 23:43:24 +0200
Subject: [PATCH] Avoid relinking already linked libs

This patch avoids collecting symbols, resolving relocs if they are
already done (usually for example libc.so during a dlopen for another
libfoo.so). This patch is purely for performance boost.
---
 src/ld_so/linker.rs | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs
index 34030513..5f7644bd 100644
--- a/src/ld_so/linker.rs
+++ b/src/ld_so/linker.rs
@@ -1,6 +1,6 @@
 use alloc::{
     boxed::Box,
-    collections::BTreeMap,
+    collections::{BTreeMap, BTreeSet},
     rc::Rc,
     string::{String, ToString},
     vec::Vec,
@@ -350,12 +350,15 @@ impl Linker {
     ) -> Result<Option<usize>> {
         unsafe { _r_debug.state = RTLDState::RT_ADD };
         _dl_debug_state();
+        let mut skip_list = BTreeSet::new();
         let elfs = {
             let mut elfs = BTreeMap::new();
             for (name, data) in lib.objects.iter() {
                 // Skip already linked libraries
                 if !lib.mmaps.contains_key(&*name) && !self.root.mmaps.contains_key(&*name) {
                     elfs.insert(name.as_str(), Elf::parse(&data)?);
+                } else {
+                    skip_list.insert(name.as_str());
                 }
             }
             elfs
@@ -365,6 +368,9 @@ impl Linker {
         let mut tls_primary = 0;
         let mut tls_size = 0;
         for (elf_name, elf) in elfs.iter() {
+            if skip_list.contains(elf_name) {
+                continue;
+            }
             if self.verbose {
                 println!("map {}", elf_name);
             }
@@ -566,6 +572,9 @@ impl Linker {
         });
         let mut tls_ranges = BTreeMap::new();
         for (elf_name, elf) in elfs.iter() {
+            if skip_list.contains(elf_name) {
+                continue;
+            }
             let same_elf = if let Some(prog) = dso.as_ref() {
                 if prog.name == *elf_name {
                     true
@@ -690,6 +699,9 @@ impl Linker {
 
         // Perform relocations, and protect pages
         for (elf_name, elf) in elfs.iter() {
+            if skip_list.contains(elf_name) {
+                continue;
+            }
             if self.verbose {
                 println!("link {}", elf_name);
             }
@@ -888,6 +900,9 @@ impl Linker {
         // Perform indirect relocations (necessary evil), gather entry point
         let mut entry_opt = None;
         for (elf_name, elf) in elfs.iter() {
+            if skip_list.contains(elf_name) {
+                continue;
+            }
             let (_, mmap) = match lib.mmaps.get_mut(*elf_name) {
                 Some(some) => some,
                 None => continue,
-- 
GitLab