diff --git a/.gitignore b/.gitignore index 6c439934ff..e7dcd0d68d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ sysroot/ *.swp *.swo /.vim +.vscode/ + diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 731634dd32..0000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "cmake.ignoreCMakeListsMissing": true, - "editor.formatOnSave": true -} \ No newline at end of file diff --git a/Makefile b/Makefile index 3c10c9d893..bdb822d45c 100644 --- a/Makefile +++ b/Makefile @@ -133,6 +133,10 @@ $(BUILD)/$(PROFILE)/libc.so: $(BUILD)/$(PROFILE)/librelibc.a $(BUILD)/openlibm/l $(LINKFLAGS) \ -o $@ +$(BUILD)/$(PROFILE)/ld_so: $(BUILD)/$(PROFILE)/ld_so.o $(BUILD)/$(PROFILE)/crti.o $(BUILD)/$(PROFILE)/libc.a $(BUILD)/$(PROFILE)/crtn.o + # TODO: merge ld.so with libc.so: --dynamic-list=dynamic-list-file + $(LD) --shared -Bsymbolic --no-relax -T ld_so/ld_script/$(TARGET).ld --allow-multiple-definition --gc-sections $^ -o $@ + # Debug targets $(BUILD)/debug/libc.a: $(BUILD)/debug/librelibc.a $(BUILD)/openlibm/libopenlibm.a @@ -166,9 +170,6 @@ $(BUILD)/debug/ld_so.o: $(SRC) $(CARGO) rustc --manifest-path ld_so/Cargo.toml $(CARGOFLAGS) -- --emit obj=$@ -C panic=abort -g -C debug-assertions=no $(RUSTCFLAGS) touch $@ -$(BUILD)/debug/ld_so: $(BUILD)/debug/ld_so.o $(BUILD)/debug/crti.o $(BUILD)/debug/libc.a $(BUILD)/debug/crtn.o - $(LD) --no-relax -T ld_so/ld_script/$(TARGET).ld --allow-multiple-definition --gc-sections $^ -o $@ - # Release targets $(BUILD)/release/libc.a: $(BUILD)/release/librelibc.a $(BUILD)/openlibm/libopenlibm.a @@ -204,9 +205,6 @@ $(BUILD)/release/ld_so.o: $(SRC) $(CARGO) rustc --release --manifest-path ld_so/Cargo.toml $(CARGOFLAGS) -- --emit obj=$@ -C panic=abort $(RUSTCFLAGS) touch $@ -$(BUILD)/release/ld_so: $(BUILD)/release/ld_so.o $(BUILD)/release/crti.o $(BUILD)/release/libc.a $(BUILD)/release/crtn.o - $(LD) --no-relax -T ld_so/ld_script/$(TARGET).ld --allow-multiple-definition --gc-sections $^ -o $@ - # Other targets $(BUILD)/openlibm: openlibm @@ -216,6 +214,6 @@ $(BUILD)/openlibm: openlibm mv $@.partial $@ touch $@ -$(BUILD)/openlibm/libopenlibm.a: $(BUILD)/openlibm $(BUILD)/release/librelibc.a +$(BUILD)/openlibm/libopenlibm.a: $(BUILD)/openlibm $(BUILD)/$(PROFILE)/librelibc.a $(MAKE) -s AR=$(AR) CC="$(CC_WRAPPER) $(CC)" LD=$(LD) CPPFLAGS="$(CPPFLAGS) -fno-stack-protector -I$(shell pwd)/include -I$(TARGET_HEADERS)" -C $< libopenlibm.a ./renamesyms.sh "$@" "$(BUILD)/release/deps/" diff --git a/ld_so/src/lib.rs b/ld_so/src/lib.rs index 6c7d4736a9..e68f260ef6 100644 --- a/ld_so/src/lib.rs +++ b/ld_so/src/lib.rs @@ -7,6 +7,9 @@ use core::arch::global_asm; #[cfg(target_arch = "aarch64")] global_asm!( " +.weak _DYNAMIC +.hidden _DYNAMIC + .global _start _start: mov x28, sp @@ -14,7 +17,9 @@ _start: and sp, x28, #0xfffffffffffffff0 adr x1, _start mov x0, x28 - // ld_so_start(stack=x0, ld_entry=x1) + adrp x2, _DYNAMIC + add x2, x2, #:lo12:_DYNAMIC + // ld_so_start(stack=x0, ld_entry=x1, dynamic=x2) bl relibc_ld_so_start // restore original stack, clear registers, and jump to the new start function mov sp, x28 @@ -69,6 +74,9 @@ _start: #[cfg(target_arch = "x86_64")] global_asm!( " +.weak _DYNAMIC +.hidden _DYNAMIC + .globl _start _start: lea rsi, [rip + _start] @@ -77,8 +85,9 @@ _start: mov rbp, rsp and rsp, 0xfffffffffffffff0 - # Call ld_so_start(stack=rdi, ld_entry=rsi) + # Call ld_so_start(stack=rdi, ld_entry=rsi, dynamic=rdx) mov rdi, rbp + lea rdx, [rip + _DYNAMIC] call relibc_ld_so_start # Restore original stack, clear registers, and jump to new start function diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index 90a7c1c168..f094733896 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -1,4 +1,4 @@ -use core::{cell::SyncUnsafeCell, cmp, fmt::Debug}; +use core::{cell::SyncUnsafeCell, cmp, fmt::Debug, ops::Range}; use crate::{ DYNAMIC_PROC_INFO, RtTcb, StaticProcInfo, @@ -11,6 +11,7 @@ use crate::{ use alloc::{boxed::Box, vec}; +use goblin::elf::header::ET_DYN; //TODO: allow use of either 32-bit or 64-bit programs #[cfg(target_pointer_width = "32")] use goblin::elf32::{ @@ -37,11 +38,13 @@ pub enum FexecResult { }, } pub struct InterpOverride { - phs: Box<[u8]>, + phdrs_vaddr: usize, at_entry: usize, at_phnum: usize, at_phent: usize, name: Box<[u8]>, + min_mmap_addr: usize, + grants_fd: usize, } pub struct ExtraInfo<'a> { @@ -78,7 +81,9 @@ pub fn fexec_impl( pread_all(&image_file, 0, &mut header_bytes)?; let header = Header::from_bytes(&header_bytes); - let grants_fd = { + let grants_fd = if let Some(interp) = interp_override.as_ref() { + FdGuard::new(interp.grants_fd).to_upper()? + } else { let current_addrspace_fd = thread_fd.dup(b"addrspace")?; current_addrspace_fd.dup(b"empty")?.to_upper()? }; @@ -99,13 +104,50 @@ pub fn fexec_impl( let phs = &mut phs_raw[size_of::
()..]; // TODO: Remove clone, but this would require more as_refs and as_muts - let mut min_mmap_addr = PAGE_SIZE; + let mut min_mmap_addr = interp_override + .as_ref() + .map(|interp| interp.min_mmap_addr) + .unwrap_or(PAGE_SIZE); let mut update_min_mmap_addr = |addr: usize, size: usize| { min_mmap_addr = cmp::max(min_mmap_addr, (addr + size).next_multiple_of(PAGE_SIZE)); }; pread_all(&image_file, u64::from(header.e_phoff), phs).map_err(|_| Error::new(EIO))?; + let mut span: Option> = None; + for ph_idx in 0..phnum { + let ph_bytes = &phs[ph_idx * phentsize..(ph_idx + 1) * phentsize]; + let segment: &ProgramHeader = + plain::from_bytes(ph_bytes).map_err(|_| Error::new(EINVAL))?; + if segment.p_type != PT_LOAD { + continue; + } + + let voff = segment.p_vaddr as usize % PAGE_SIZE; + let vaddr = segment.p_vaddr as usize - voff; + let vsize = (segment.p_memsz as usize + voff).next_multiple_of(segment.p_align as usize); + let b = vaddr..vaddr + vsize; + + span = Some(if let Some(a) = span { + a.start.min(b.start)..a.end.max(b.end) + } else { + b + }); + } + let span = span.expect("ELF executables must contain at least one `PT_LOAD` segment"); + let base_addr = if header.e_type == ET_DYN { + // PIE + let span_size = (span.end - span.start).next_multiple_of(PAGE_SIZE); + let addr = mmap_anon_remote(&grants_fd, 0, 0, span_size, MapFlags::PROT_NONE)?; + update_min_mmap_addr(addr, span_size); + addr + } else { + 0 + }; + + let mut phdrs_vaddr = 0; + let mut interpreter = None; + for ph_idx in 0..phnum { let ph_bytes = &phs[ph_idx * phentsize..(ph_idx + 1) * phentsize]; let segment: &ProgramHeader = @@ -129,16 +171,7 @@ pub fn fexec_impl( let mut interp = vec![0_u8; segment.p_filesz as usize]; pread_all(&image_file, u64::from(segment.p_offset), &mut interp)?; - return Ok(FexecResult::Interp { - path: interp.into_boxed_slice(), - interp_override: InterpOverride { - at_entry: header.e_entry as usize, - at_phnum: phnum, - at_phent: phentsize, - phs: phs_raw.into_boxed_slice(), - name: path.into(), - }, - }); + interpreter = Some(interp.into_boxed_slice()); } PT_LOAD => { let voff = segment.p_vaddr as usize % PAGE_SIZE; @@ -157,18 +190,25 @@ pub fn fexec_impl( mmap_anon_remote( &grants_fd, 0, - vaddr, + base_addr + vaddr, total_page_count * PAGE_SIZE, - flags | MapFlags::MAP_FIXED_NOREPLACE, + flags | MapFlags::MAP_FIXED, )?; + if segment.p_offset <= header.e_phoff + && header.e_phoff < segment.p_offset + segment.p_filesz + { + phdrs_vaddr = + (header.e_phoff - segment.p_offset + segment.p_vaddr) as usize + base_addr; + } + // TODO: Attempt to mmap with MAP_PRIVATE directly from the image file instead. if filesz > 0 { let (_guard, dst_memory) = unsafe { MmapGuard::map_mut_anywhere( &grants_fd, - vaddr, // offset + base_addr + vaddr, // offset (voff + filesz).next_multiple_of(PAGE_SIZE), // size )? }; @@ -178,13 +218,26 @@ pub fn fexec_impl( &mut dst_memory[voff..voff + filesz], )?; } - - update_min_mmap_addr(vaddr, total_page_count * PAGE_SIZE); } _ => continue, } } + if let Some(interpreter_path) = interpreter { + return Ok(FexecResult::Interp { + path: interpreter_path, + interp_override: InterpOverride { + at_entry: header.e_entry as usize, + at_phnum: phnum, + at_phent: phentsize, + phdrs_vaddr, + name: path.into(), + min_mmap_addr, + grants_fd: grants_fd.take(), + }, + }); + } + mmap_anon_remote( &grants_fd, 0, @@ -234,43 +287,21 @@ pub fn fexec_impl( Ok(()) }; - let pheaders_to_convey = if let Some(ref r#override) = interp_override { - &*r#override.phs - } else { - &*phs_raw - }; - let pheaders_size_aligned = pheaders_to_convey.len().next_multiple_of(PAGE_SIZE); - let pheaders = mmap_anon_remote( - &grants_fd, - 0, - 0, - pheaders_size_aligned, - MapFlags::PROT_READ | MapFlags::PROT_WRITE, - )?; - update_min_mmap_addr(pheaders, pheaders_size_aligned); - unsafe { - let (_guard, memory) = - MmapGuard::map_mut_anywhere(&grants_fd, pheaders, pheaders_size_aligned)?; - - memory[..pheaders_to_convey.len()].copy_from_slice(pheaders_to_convey); - } - mprotect_remote( - &grants_fd, - pheaders, - pheaders_size_aligned, - MapFlags::PROT_READ, - )?; - push(0)?; push(AT_NULL)?; - push(header.e_entry as usize)?; if let Some(ref r#override) = interp_override { - push(AT_BASE)?; push(r#override.at_entry)?; + push(AT_ENTRY)?; + push(base_addr)?; + push(AT_BASE)?; + push(r#override.phdrs_vaddr)?; + push(AT_PHDR)?; + } else { + push(header.e_entry as usize)?; + push(AT_ENTRY)?; + push(phdrs_vaddr)?; + push(AT_PHDR)?; } - push(AT_ENTRY)?; - push(pheaders + size_of::
())?; - push(AT_PHDR)?; push( interp_override .as_ref() @@ -413,7 +444,7 @@ pub fn fexec_impl( let _ = addrspace_selection_fd.write(&create_set_addr_space_buf( grants_fd.as_raw_fd(), - header.e_entry as usize, + base_addr + header.e_entry as usize, sp, )); diff --git a/src/ld_so/dso.rs b/src/ld_so/dso.rs index 5e94d0f636..0533b3117a 100644 --- a/src/ld_so/dso.rs +++ b/src/ld_so/dso.rs @@ -64,6 +64,11 @@ mod shim { pub use shim::*; +// TODO: missing from the `object` crate +pub const DT_RELRSZ: u32 = 35; +pub const DT_RELR: u32 = 36; +pub const DT_RELRENT: u32 = 37; + /// Undefined Symbol Index pub const STN_UNDEF: SymbolIndex = SymbolIndex(0); @@ -170,11 +175,11 @@ unsafe impl Send for Dynamic<'_> {} unsafe impl Sync for Dynamic<'_> {} #[derive(Debug)] -struct Relocation { - offset: usize, - addend: Option, - sym: SymbolIndex, - kind: RelocationKind, +pub(super) struct Relocation { + pub(super) offset: usize, + pub(super) addend: Option, + pub(super) sym: SymbolIndex, + pub(super) kind: RelocationKind, } #[cfg(target_pointer_width = "32")] @@ -522,8 +527,8 @@ impl DSO { }; _r_debug .lock() - .insert_first(addr, path, addr + l_ld as usize); - slice::from_raw_parts_mut(addr as *mut u8, size) + .insert_first(addr + bounds.0, path, addr + l_ld as usize); + slice::from_raw_parts_mut((addr + bounds.0) as *mut u8, size) } else { let (start, end) = bounds; let size = end - start; @@ -662,10 +667,6 @@ impl DSO { is_pie: bool, (_, entries): (&ProgramHeader, &[Dyn]), ) -> object::Result<(Dynamic<'a>, Option)> { - const DT_RELRSZ: u32 = 35; - const DT_RELR: u32 = 36; - const DT_RELRENT: u32 = 37; - let mut runpath = None; let mut got = None; let mut needed = vec![]; @@ -1078,34 +1079,8 @@ impl DSO { let global_scope = GLOBAL_SCOPE.read(); let base = self.mmap.as_ptr(); - // Apply DT_RELR relative relocations. - let mut addr = ptr::null_mut(); - for &entry in self.dynamic.relr { - if entry & 1 == 0 { - // An even entry sets up `addr` for subsequent odd entries. - unsafe { - addr = base.add(entry) as *mut usize; - *addr += base as usize; - addr = addr.add(1); - } - } else { - // An odd entry indicates a bitmap describing at maximum 63 - // (for 64-bit) or 31 (for 32-bit) locations following `addr`. - // Odd entries can be chained. - let mut entry = entry >> 1; - let mut i = 0; - while entry != 0 { - if entry & 1 != 0 { - unsafe { - *addr.add(i) += base as usize; - } - } - entry >>= 1; - i += 1; - } - - addr = unsafe { addr.add(CHAR_BITS * size_of::() - 1) }; - } + unsafe { + apply_relr(base, self.dynamic.relr); } self.dynamic @@ -1295,3 +1270,35 @@ __tlsdesc_dynamic: unimp " ); + +/// Applies [`DT_RELR`] relative relocations. +pub unsafe fn apply_relr(base: *const u8, relr: &[Relr]) { + let mut addr = ptr::null_mut(); + for &entry in relr { + if entry & 1 == 0 { + // An even entry sets up `addr` for subsequent odd entries. + unsafe { + addr = base.add(entry) as *mut usize; + *addr += base as usize; + addr = addr.add(1); + } + } else { + // An odd entry indicates a bitmap describing at maximum 63 + // (for 64-bit) or 31 (for 32-bit) locations following `addr`. + // Odd entries can be chained. + let mut entry = entry >> 1; + let mut i = 0; + while entry != 0 { + if entry & 1 != 0 { + unsafe { + *addr.add(i) += base as usize; + } + } + entry >>= 1; + i += 1; + } + + addr = unsafe { addr.add(CHAR_BITS * size_of::() - 1) }; + } + } +} diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index f740f52dda..03380d25b9 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -348,7 +348,7 @@ bitflags::bitflags! { #[derive(Default)] pub struct Config { - debug_flags: DebugFlags, + pub debug_flags: DebugFlags, library_path: Option, /// Resolve symbols at program startup. bind_now: bool, diff --git a/src/ld_so/start.rs b/src/ld_so/start.rs index c52cbc9bd5..355f1474fa 100644 --- a/src/ld_so/start.rs +++ b/src/ld_so/start.rs @@ -1,5 +1,7 @@ // Start code adapted from https://gitlab.redox-os.org/redox-os/relibc/blob/master/src/start.rs +use core::slice; + use alloc::{ borrow::ToOwned, boxed::Box, @@ -7,14 +9,26 @@ use alloc::{ string::{String, ToString}, vec::Vec, }; +use object::{ + NativeEndian, + elf::{self, PT_DYNAMIC, PT_PHDR}, + read::elf::{Dyn as _, ProgramHeader as _}, +}; use crate::{ c_str::CStr, header::{ - sys_auxv::{AT_ENTRY, AT_PHDR}, + elf::{AT_BASE, AT_ENTRY, AT_PHDR, AT_PHENT, AT_PHNUM}, unistd, }, - platform::{get_auxv, get_auxvs, types::c_char}, + ld_so::{ + dso::{ + DT_RELR, DT_RELRENT, DT_RELRSZ, Dyn, ProgramHeader, Rel, Rela, Relocation, + RelocationKind, Relr, apply_relr, + }, + linker::DebugFlags, + }, + platform::{auxv_iter, get_auxvs, types::c_char}, start::Stack, sync::mutex::Mutex, }; @@ -149,7 +163,155 @@ fn resolve_path_name( } #[unsafe(no_mangle)] -pub unsafe extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) -> usize { +pub unsafe extern "C" fn relibc_ld_so_start( + sp: &'static mut Stack, + ld_entry: usize, + dynamic: *const Dyn, +) -> usize { + // Relocate ourselves. + // + // This function is very delicate as it must **not** contain relocations itself. References to + // external symbols **cannot** be made until `stage2()` so, this function might not be very + // elegant. + // + // At this stage the TCB is not setup either so `expect_notls` must be used instead of `expect` + // and `unwrap`. + let mut at_phdr = None; + let mut at_phnum = None; + let mut at_phent = None; + let mut at_base = None; + let mut at_entry = None; + for [kind, value] in unsafe { auxv_iter(sp.auxv().cast::()) } { + match kind { + AT_PHDR => at_phdr = Some(value as *const ProgramHeader), + AT_PHNUM => at_phnum = Some(value), + AT_PHENT => at_phent = Some(value), + AT_BASE => at_base = Some(value), + AT_ENTRY => at_entry = Some(value), + _ => {} + } + } + + let at_phdr = at_phdr.expect_notls("`AT_PHDR` must be present"); + let at_phnum = at_phnum.expect_notls("`AT_PHNUM` must be present if `AT_PHDR` is"); + let at_phent = at_phent.expect_notls("`AT_PHENT` must be present if `AT_PHDR` is"); + assert!(!at_phdr.is_null() && at_phnum != 0 && at_phent == size_of::()); + let phdrs = unsafe { slice::from_raw_parts(at_phdr, at_phnum) }; + + let at_entry = at_entry.expect_notls("`AT_ENTRY` must be present"); + let at_base = at_base.unwrap_or_default(); + + let self_base = if at_base != 0 { + at_base + } else { + let ph = phdrs + .iter() + .find(|ph| ph.p_type(NativeEndian) == PT_DYNAMIC as u32) + .unwrap(); + unsafe { dynamic.byte_sub(ph.p_vaddr(NativeEndian) as usize) as usize } + }; + + let is_manual = at_entry == ld_entry; // Whether the dynamic linker was invoked as a command. + + let mut i = dynamic; + let mut rela_ptr = None; + let mut rela_len = None; + let mut relr_ptr = None; + let mut relr_len = None; + let mut rel_ptr = None; + let mut rel_len = None; + loop { + let entry = unsafe { &*i }; + let val = entry.d_val(NativeEndian); + let ptr = val as *const u8; + match entry.d_tag(NativeEndian) as u32 { + elf::DT_NULL => break, + elf::DT_RELA => rela_ptr = Some(ptr.cast::()), + elf::DT_RELASZ => rela_len = Some(val as usize / size_of::()), + elf::DT_RELAENT => { + assert_eq!(val as usize, size_of::(),); + } + elf::DT_REL => rel_ptr = Some(ptr.cast::()), + elf::DT_RELSZ => rel_len = Some(val as usize / size_of::()), + elf::DT_RELENT => { + assert_eq!(val as usize, size_of::()); + } + DT_RELR => relr_ptr = Some(ptr.cast::()), + DT_RELRSZ => relr_len = Some(val as usize / size_of::()), + DT_RELRENT => { + assert_eq!(val as usize, size_of::()); + } + _ => {} + } + i = unsafe { i.add(1) }; + } + + unsafe fn get_array<'a, T>( + ptr: Option<*const T>, + len: Option, + base_addr: usize, + ) -> &'a [T] { + if let Some(ptr) = ptr { + let len = len.expect_notls("dynamic entry was present without it's corresponding size"); + unsafe { core::slice::from_raw_parts(ptr.byte_add(base_addr), len) } + } else { + &[] + } + } + + fn do_relocs<'a, T>(relocs: &'a [T], self_base: usize) + where + Relocation: From<&'a T>, + { + for reloc in relocs { + let reloc: Relocation = reloc.into(); + let ptr = (reloc.offset + self_base) as *mut usize; + match reloc.kind { + RelocationKind::RELATIVE => { + unsafe { *ptr = self_base + reloc.addend.unwrap_or_default() }; + } + _ => {} + } + } + } + + let rela = unsafe { get_array::(rela_ptr, rela_len, self_base) }; + let rel = unsafe { get_array::(rel_ptr, rel_len, self_base) }; + do_relocs(rela, self_base); + do_relocs(rel, self_base); + + unsafe { + let relr = get_array(relr_ptr, relr_len, self_base); + apply_relr(self_base as *const u8, relr); + } + + let mut base_addr = None; + if !is_manual { + // if we are not running in manual mode, then the main + // program is already loaded by the kernel and we want + // to use it. on redox, we treat it the same. + for ph in phdrs.iter() { + if ph.p_type(NativeEndian) == PT_PHDR { + assert!(base_addr.is_none(), "`PT_PHDR` cannot occur more than once"); + base_addr = Some(unsafe { + phdrs + .as_ptr() + .cast::() + .sub(ph.p_vaddr(NativeEndian) as usize) + } as usize); + } + } + } + + stage2(sp, self_base, is_manual, base_addr) +} + +fn stage2( + sp: &'static mut Stack, + self_base: usize, + is_manual: bool, + base_addr: Option, +) -> usize { // Setup TCB for ourselves. unsafe { #[cfg(target_os = "redox")] @@ -225,14 +387,8 @@ pub unsafe extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: us crate::platform::environ = crate::platform::OUR_ENVIRON.unsafe_mut().as_mut_ptr(); } - let is_manual = if let Some(img_entry) = get_auxv(&auxv, AT_ENTRY) { - img_entry == ld_entry - } else { - true - }; - // we might need global lock for this kind of stuff - _r_debug.lock().r_ldbase = ld_entry; + _r_debug.lock().r_ldbase = self_base; // TODO: Fix memory leak, although minimal. #[cfg(target_os = "redox")] @@ -264,20 +420,15 @@ pub unsafe extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: us } }; - // if we are not running in manual mode, then the main - // program is already loaded by the kernel and we want - // to use it. on redox, we treat it the same. - let base_addr = { - let mut base = None; - if !is_manual && cfg!(not(target_os = "redox")) { - let phdr = get_auxv(&auxv, AT_PHDR).unwrap(); - if phdr != 0 { - base = Some(phdr - SIZEOF_EHDR); - } + let config = Config::from_env(&envs); + if config.debug_flags.contains(DebugFlags::LOAD) { + println!("[ld.so]: relocated self at {self_base:#x}!"); + if let Some(base_addr) = base_addr { + println!("[ld.so]: executable has been already loaded at {base_addr:#x?}"); } - base - }; - let mut linker = Linker::new(Config::from_env(&envs)); + } + + let mut linker = Linker::new(config); let entry = match linker.load_program(&path, base_addr) { Ok(entry) => entry, Err(err) => { diff --git a/src/platform/mod.rs b/src/platform/mod.rs index d489485b38..c4250cfbd8 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -280,18 +280,18 @@ impl Write for CountingWriter { // get_auxv. #[cold] -unsafe fn auxv_iter<'a>(ptr: *const usize) -> impl Iterator + 'a { +pub unsafe fn auxv_iter<'a>(ptr: *const usize) -> impl Iterator + 'a { struct St(*const usize); impl Iterator for St { type Item = [usize; 2]; fn next(&mut self) -> Option { unsafe { - if self.0.read() == self::auxv_defs::AT_NULL { + if *self.0 == self::auxv_defs::AT_NULL { return None; } - let kind = self.0.read(); - let value = self.0.add(1).read(); + let kind = *self.0; + let value = *self.0.add(1); self.0 = self.0.add(2); Some([kind, value])