diff --git a/Makefile b/Makefile index a132c7274c..0076226f8a 100644 --- a/Makefile +++ b/Makefile @@ -110,7 +110,7 @@ $(BUILD)/debug/libc.a: $(BUILD)/debug/librelibc.a $(BUILD)/pthreads-emb/libpthre $(AR) -M < "$@.mri" $(BUILD)/debug/libc.so: $(BUILD)/debug/librelibc.a $(BUILD)/pthreads-emb/libpthread.a $(BUILD)/openlibm/libopenlibm.a - $(CC) -nostdlib -shared -Wl,--allow-multiple-definition -Wl,--whole-archive $^ -Wl,--no-whole-archive -o $@ + $(CC) -nostdlib -shared -Wl,--allow-multiple-definition -Wl,--whole-archive $^ -Wl,--no-whole-archive -Wl,-soname,libc.so.6 -o $@ $(BUILD)/debug/librelibc.a: $(SRC) CARGO_INCREMENTAL=0 $(CARGO) rustc $(CARGOFLAGS) -- --emit link=$@ $(RUSTCFLAGS) @@ -149,7 +149,7 @@ $(BUILD)/release/libc.a: $(BUILD)/release/librelibc.a $(BUILD)/pthreads-emb/libp $(AR) -M < "$@.mri" $(BUILD)/release/libc.so: $(BUILD)/release/librelibc.a $(BUILD)/pthreads-emb/libpthread.a $(BUILD)/openlibm/libopenlibm.a - $(CC) -nostdlib -shared -Wl,--allow-multiple-definition -Wl,--whole-archive $^ -Wl,--no-whole-archive -o $@ + $(CC) -nostdlib -shared -Wl,--allow-multiple-definition -Wl,--whole-archive $^ -Wl,--no-whole-archive -Wl,-soname,libc.so.6 -o $@ $(BUILD)/release/librelibc.a: $(SRC) CARGO_INCREMENTAL=0 $(CARGO) rustc --release $(CARGOFLAGS) -- --emit link=$@ $(RUSTCFLAGS) diff --git a/src/header/stdio/printf.rs b/src/header/stdio/printf.rs index f6f6f18341..d06570fa86 100644 --- a/src/header/stdio/printf.rs +++ b/src/header/stdio/printf.rs @@ -690,7 +690,6 @@ unsafe fn inner_printf(w: W, format: *const c_char, mut ap: VaList) -> _ => None, }; - let index = arg.index.map(|i| i - 1).unwrap_or_else(|| { if fmtkind == FmtKind::Percent { 0 diff --git a/src/ld_so/callbacks.rs b/src/ld_so/callbacks.rs index 031ecb47ad..d53f21561b 100644 --- a/src/ld_so/callbacks.rs +++ b/src/ld_so/callbacks.rs @@ -1,4 +1,4 @@ -use super::linker::{DSO, Linker, Symbol}; +use super::linker::{Linker, Symbol, DSO}; use alloc::boxed::Box; use goblin::error::Result; diff --git a/src/ld_so/library.rs b/src/ld_so/library.rs index 156234b9c4..88958e01c8 100644 --- a/src/ld_so/library.rs +++ b/src/ld_so/library.rs @@ -1,10 +1,10 @@ +use super::linker::Symbol; use alloc::{ boxed::Box, collections::{BTreeMap, BTreeSet}, string::String, vec::Vec, }; -use super::linker::Symbol; #[derive(Default, Debug)] pub struct DepTree { diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index ee1f3ee7d0..670d38e776 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, @@ -15,9 +15,7 @@ use goblin::{ header::ET_DYN, program_header, r#dyn::{Dyn, DT_DEBUG}, - reloc, - sym, - Elf, + reloc, sym, Elf, }, error::{Error, Result}, }; @@ -25,7 +23,7 @@ use goblin::{ use crate::{ c_str::CString, fs::File, - header::{fcntl, sys_mman, unistd, errno::STR_ERROR}, + header::{errno::STR_ERROR, fcntl, sys_mman, unistd}, io::Read, platform::{errno, types::c_void}, }; @@ -147,9 +145,14 @@ impl Linker { deps.push(dep); } } - - lib.objects.insert(name.to_string(), data); - + let elf = Elf::parse(&data)?; + let key = match elf.soname { + Some(soname) => soname, + _ => name, + }; + if !lib.objects.contains_key(key) { + lib.objects.insert(key.to_string(), data); + } return Ok(deps); } @@ -337,12 +340,15 @@ impl Linker { ) -> Result> { 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 @@ -352,6 +358,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); } @@ -447,7 +456,9 @@ impl Linker { let mut start = addr; for (vaddr, vsize) in ranges.iter() { if start < addr + vaddr { - println!("mmap({:#x}, {})", start, addr + vaddr - start); + if self.verbose { + println!("mmap({:#x}, {})", start, addr + vaddr - start); + } let mut flags = sys_mman::MAP_ANONYMOUS | sys_mman::MAP_PRIVATE; if start != 0 { flags |= sys_mman::MAP_FIXED_NOREPLACE; @@ -461,11 +472,19 @@ impl Linker { -1, 0, ); - if ptr as usize == !0 /* MAP_FAILED */ { - return Err(Error::Malformed(format!("failed to map {}. errno: {}", elf_name, STR_ERROR[errno as usize]))); + if ptr as usize == !0 + /* MAP_FAILED */ + { + return Err(Error::Malformed(format!( + "failed to map {}. errno: {}", + elf_name, STR_ERROR[errno as usize] + ))); } if start as *mut c_void != ptr::null_mut() { - assert_eq!(ptr, start as *mut c_void, "mmap must always map on the destination we requested"); + assert_eq!( + ptr, start as *mut c_void, + "mmap must always map on the destination we requested" + ); } } start = addr + vaddr + vsize @@ -476,11 +495,16 @@ impl Linker { sys_mman::PROT_READ | sys_mman::PROT_WRITE, ); _r_debug.insert_first(addr as usize, &elf_name, addr + l_ld as usize); - (addr as usize, slice::from_raw_parts_mut(addr as *mut u8, size)) + ( + addr as usize, + slice::from_raw_parts_mut(addr as *mut u8, size), + ) } else { let (start, end) = bounds; let size = end - start; - println!("mmap({:#x}, {})", start, size); + if self.verbose { + println!("mmap({:#x}, {})", start, size); + } let mut flags = sys_mman::MAP_ANONYMOUS | sys_mman::MAP_PRIVATE; if start != 0 { flags |= sys_mman::MAP_FIXED_NOREPLACE; @@ -494,11 +518,19 @@ impl Linker { -1, 0, ); - if ptr as usize == !0 /* MAP_FAILED */ { - return Err(Error::Malformed(format!("failed to map {}. errno: {}", elf_name, STR_ERROR[errno as usize]))); + if ptr as usize == !0 + /* MAP_FAILED */ + { + return Err(Error::Malformed(format!( + "failed to map {}. errno: {}", + elf_name, STR_ERROR[errno as usize] + ))); } if start as *mut c_void != ptr::null_mut() { - assert_eq!(ptr, start as *mut c_void, "mmap must always map on the destination we requested"); + assert_eq!( + ptr, start as *mut c_void, + "mmap must always map on the destination we requested" + ); } ptr::write_bytes(ptr as *mut u8, 0, size); _r_debug.insert(ptr as usize, &elf_name, ptr as usize + l_ld as usize); @@ -534,6 +566,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 @@ -580,7 +615,8 @@ impl Linker { }; let mmap_data = { - let range = ph.p_vaddr as usize - base_addr..ph.p_vaddr as usize + obj_data.len() - base_addr; + let range = ph.p_vaddr as usize - base_addr + ..ph.p_vaddr as usize + obj_data.len() - base_addr; match mmap.get_mut(range.clone()) { Some(some) => some, None => { @@ -588,7 +624,7 @@ impl Linker { return Err(Error::Malformed(format!( "failed to write {:x?}", range - ))) + ))); } } }; @@ -657,6 +693,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); } @@ -671,7 +710,6 @@ impl Linker { // reloc::r_to_str(rel.r_type, elf.header.e_machine), // rel // ); - let symbol = if rel.r_sym > 0 { let sym = elf.dynsyms.get(rel.r_sym).ok_or(Error::Malformed(format!( "missing symbol for relocation {:?}", @@ -680,18 +718,20 @@ impl Linker { let name = elf.dynstrtab - .get(sym.st_name) - .ok_or(Error::Malformed(format!( - "missing name for symbol {:?}", - sym - )))??; - lib.get_sym(name) - .or_else(|| self.root.get_sym(name)) + .get(sym.st_name) + .ok_or(Error::Malformed(format!( + "missing name for symbol {:?}", + sym + )))??; + lib.get_sym(name).or_else(|| self.root.get_sym(name)) } else { None }; - let s = symbol.as_ref().map(|sym| sym.as_ptr() as usize).unwrap_or(0); + let s = symbol + .as_ref() + .map(|sym| sym.as_ptr() as usize) + .unwrap_or(0); let a = rel.r_addend.unwrap_or(0) as usize; @@ -713,7 +753,6 @@ impl Linker { } else { rel.r_offset as *mut u8 }; - let set_u64 = |value| { // println!(" set_u64 {:#x}", value); unsafe { @@ -747,9 +786,11 @@ impl Linker { reloc::R_X86_64_IRELATIVE => (), // Handled below reloc::R_X86_64_COPY => unsafe { // TODO: Make this work - let sym = symbol.as_ref().expect("R_X86_64_COPY called without valid symbol"); + let sym = symbol + .as_ref() + .expect("R_X86_64_COPY called without valid symbol"); ptr::copy_nonoverlapping(sym.as_ptr() as *const u8, ptr, sym.size as usize); - } + }, _ => { panic!( " {} unsupported", @@ -851,6 +892,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, diff --git a/src/ld_so/mod.rs b/src/ld_so/mod.rs index 1321c33c89..19dfe05f52 100644 --- a/src/ld_so/mod.rs +++ b/src/ld_so/mod.rs @@ -1,9 +1,8 @@ use core::{mem, ptr}; use goblin::elf::program_header::{self, program_header32, program_header64, ProgramHeader}; -use crate::header::sys_auxv::AT_NULL; -use crate::start::Stack; use self::tcb::{Master, Tcb}; +use crate::{header::sys_auxv::AT_NULL, start::Stack}; pub const PAGE_SIZE: usize = 4096; diff --git a/src/ld_so/start.rs b/src/ld_so/start.rs index 23296f035b..153b899265 100644 --- a/src/ld_so/start.rs +++ b/src/ld_so/start.rs @@ -10,11 +10,11 @@ use alloc::{ use crate::{ c_str::CStr, - header::{unistd, sys_auxv::AT_NULL}, + header::{sys_auxv::AT_NULL, unistd}, platform::{new_mspace, types::c_char}, start::Stack, sync::mutex::Mutex, - ALLOCATOR + ALLOCATOR, }; use super::{