Răsfoiți Sursa

Merge branch 'lD_PATH' into 'master'

L d path

See merge request redox-os/relibc!300
jD91mZM2 4 ani în urmă
părinte
comite
7b6ba2c73a
6 a modificat fișierele cu 95 adăugiri și 31 ștergeri
  1. 2 0
      .gitignore
  2. 2 2
      Makefile
  3. 13 4
      src/ld_so/access.rs
  4. 16 2
      src/ld_so/ld_script
  5. 4 14
      src/ld_so/linker.rs
  6. 58 9
      src/ld_so/start.rs

+ 2 - 0
.gitignore

@@ -2,3 +2,5 @@
 prefix/
 sysroot/
 **/target/
+.gdb_history
+*.patch

+ 2 - 2
Makefile

@@ -135,7 +135,7 @@ $(BUILD)/debug/ld_so.o: $(SRC)
 	touch $@
 
 $(BUILD)/debug/ld_so: $(BUILD)/debug/ld_so.o $(BUILD)/debug/crti.o $(BUILD)/debug/libc.a $(BUILD)/debug/crtn.o
-	$(LD) -T src/ld_so/ld_script --allow-multiple-definition --gc-sections --gc-keep-exported $^ -o $@
+	$(LD) --no-relax -T src/ld_so/ld_script --allow-multiple-definition --gc-sections --gc-keep-exported $^ -o $@
 
 # Release targets
 
@@ -174,7 +174,7 @@ $(BUILD)/release/ld_so.o: $(SRC)
 	touch $@
 
 $(BUILD)/release/ld_so: $(BUILD)/release/ld_so.o $(BUILD)/release/crti.o $(BUILD)/release/libc.a $(BUILD)/release/crtn.o
-	$(LD) -T src/ld_so/ld_script --allow-multiple-definition --gc-sections --gc-keep-exported $^ -o $@
+	$(LD) --no-relax -T src/ld_so/ld_script --allow-multiple-definition --gc-sections --gc-keep-exported $^ -o $@
 
 # Other targets
 

+ 13 - 4
src/ld_so/access.rs

@@ -1,20 +1,29 @@
 // Wrapper over the access syscall that doesn't touch errno variable,
 // Do not use outside of ld_so
 
-use crate::{c_str::CStr, platform::types::*};
-
 #[cfg(target_os = "redox")]
 use crate::header::unistd::{F_OK, R_OK, W_OK, X_OK};
+use crate::{
+    c_str::{CStr, CString},
+    platform::types::*,
+};
+
+pub fn accessible(path: &str, mode: c_int) -> c_int {
+    let path_c = CString::new(path.as_bytes()).unwrap(); /*.map_err(|err| {
+                                                             Error::Malformed(format!("invalid path '{}': {}", path, err))
+                                                         })?;*/
+    unsafe { access(path_c.as_ptr(), mode) }
+}
 
 #[cfg(target_os = "linux")]
-pub unsafe fn access(path: *const c_char, mode: c_int) -> c_int {
+unsafe fn access(path: *const c_char, mode: c_int) -> c_int {
     let path = CStr::from_ptr(path);
     syscall!(ACCESS, (path).as_ptr(), mode) as c_int
 }
 
 // Wrapper over the systemcall, Do not use outside of ld_so
 #[cfg(target_os = "redox")]
-pub unsafe fn access(path: *const c_char, mode: c_int) -> c_int {
+unsafe fn access(path: *const c_char, mode: c_int) -> c_int {
     let path = CStr::from_ptr(path).to_bytes();
     let fd = match syscall::open(path, syscall::O_CLOEXEC) {
         Ok(fd) => fd,

+ 16 - 2
src/ld_so/ld_script

@@ -8,10 +8,20 @@ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
 OUTPUT_ARCH(i386:x86-64)
 ENTRY(_start)
 SEARCH_DIR("/x86_64-unknown-redox/lib");
+SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib64");
+SEARCH_DIR("/usr/lib64/binutils/x86_64-pc-linux-gnu/2.33.164");
+SEARCH_DIR("/usr/local/lib64");
+SEARCH_DIR("/lib64");
+SEARCH_DIR("/usr/lib64");
+SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib");
+SEARCH_DIR("/usr/lib64/binutils/x86_64-pc-linux-gnu/2.33.1");
+SEARCH_DIR("/usr/local/lib");
+SEARCH_DIR("/lib");
+SEARCH_DIR("/usr/lib");
 SECTIONS
 {
   /* Read-only sections, merged into text segment: */
-  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x20000000) + SIZEOF_HEADERS;
+  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x12340000)); . = SEGMENT_START("text-segment", 0x1234000) + SIZEOF_HEADERS;
   .interp         : { *(.interp) }
   .note.gnu.build-id  : { *(.note.gnu.build-id) }
   .hash           : { *(.hash) }
@@ -46,6 +56,7 @@ SECTIONS
       *(.rela.iplt)
       PROVIDE_HIDDEN (__rela_iplt_end = .);
     }
+  . = ALIGN(CONSTANT (MAXPAGESIZE));
   .init           :
   {
     KEEP (*(SORT_NONE(.init)))
@@ -59,7 +70,6 @@ SECTIONS
     *(.text.exit .text.exit.*)
     *(.text.startup .text.startup.*)
     *(.text.hot .text.hot.*)
-    *(SORT(.text.sorted.*))
     *(.text .stub .text.* .gnu.linkonce.t.*)
     /* .gnu.warning sections are handled specially by elf.em.  */
     *(.gnu.warning)
@@ -71,6 +81,10 @@ SECTIONS
   PROVIDE (__etext = .);
   PROVIDE (_etext = .);
   PROVIDE (etext = .);
+  . = ALIGN(CONSTANT (MAXPAGESIZE));
+  /* Adjust the address for the rodata segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
   .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
   .rodata1        : { *(.rodata1) }
   .eh_frame_hdr   : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }

+ 4 - 14
src/ld_so/linker.rs

@@ -31,7 +31,7 @@ use crate::{
 };
 
 use super::{
-    access::access,
+    access::accessible,
     callbacks::LinkerCallbacks,
     debug::{RTLDDebug, RTLDState, _dl_debug_state, _r_debug},
     library::{DepTree, Library},
@@ -39,10 +39,10 @@ use super::{
     PAGE_SIZE,
 };
 #[cfg(target_os = "redox")]
-const PATH_SEP: char = ';';
+pub const PATH_SEP: char = ';';
 
 #[cfg(target_os = "linux")]
-const PATH_SEP: char = ':';
+pub const PATH_SEP: char = ':';
 
 pub struct DSO {
     pub name: String,
@@ -178,18 +178,8 @@ impl Linker {
                 if self.verbose {
                     println!("check {}", path);
                 }
-                let access = unsafe {
-                    let path_c = CString::new(path.as_bytes()).map_err(|err| {
-                        Error::Malformed(format!("invalid path '{}': {}", path, err))
-                    })?;
-
-                    // TODO: Use R_OK | X_OK
-                    // We cannot use unix stdlib because errno is thead local variable
-                    // and fs:[0] is not set yet.
-                    access(path_c.as_ptr(), unistd::F_OK) == 0
-                };
 
-                if access {
+                if accessible(&path, unistd::F_OK) == 0 {
                     return Ok(Some(self.load_recursive(name, &path, lib)?));
                 }
             }

+ 58 - 9
src/ld_so/start.rs

@@ -1,6 +1,12 @@
 // Start code adapted from https://gitlab.redox-os.org/redox-os/relibc/blob/master/src/start.rs
 
-use alloc::{borrow::ToOwned, boxed::Box, collections::BTreeMap, string::String, vec::Vec};
+use alloc::{
+    borrow::ToOwned,
+    boxed::Box,
+    collections::BTreeMap,
+    string::{String, ToString},
+    vec::Vec,
+};
 
 use crate::{
     c_str::CStr,
@@ -12,8 +18,9 @@ use crate::{
 };
 
 use super::{
+    access::accessible,
     debug::_r_debug,
-    linker::{Linker, DSO},
+    linker::{Linker, DSO, PATH_SEP},
     tcb::Tcb,
 };
 use crate::header::sys_auxv::{AT_ENTRY, AT_PHDR};
@@ -116,9 +123,41 @@ unsafe fn adjust_stack(sp: &'static mut Stack) {
             break;
         }
     }
-
     sp.argc -= 1;
 }
+
+fn resolve_path_name(
+    name_or_path: &str,
+    envs: &BTreeMap<String, String>,
+) -> Option<(String, String)> {
+    if accessible(name_or_path, unistd::F_OK) == 0 {
+        return Some((
+            name_or_path.to_string(),
+            name_or_path
+                .split("/")
+                .collect::<Vec<&str>>()
+                .last()
+                .unwrap()
+                .to_string(),
+        ));
+    }
+    if name_or_path.split("/").collect::<Vec<&str>>().len() != 1 {
+        return None;
+    }
+
+    let env_path = envs.get("PATH")?;
+    for part in env_path.split(PATH_SEP) {
+        let path = if part.is_empty() {
+            format!("./{}", name_or_path)
+        } else {
+            format!("{}/{}", part, name_or_path)
+        };
+        if accessible(&path, unistd::F_OK) == 0 {
+            return Some((path.to_string(), name_or_path.to_string()));
+        }
+    }
+    None
+}
 #[no_mangle]
 pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) -> usize {
     // First thing we initialize the mspace
@@ -149,7 +188,7 @@ pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) ->
         None => "/lib".to_owned(),
     };
 
-    let path = if is_manual {
+    let name_or_path = if is_manual {
         // ld.so is run directly by user and not via execve() or similar systemcall
         println!("argv: {:#?}", argv);
         println!("envs: {:#?}", envs);
@@ -161,13 +200,23 @@ pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) ->
             loop {}
         }
         unsafe { adjust_stack(sp) };
-        &argv[1]
+        argv[1].to_string()
     } else {
-        &argv[0]
+        argv[0].to_string()
     };
-    // if we are not running in manual mode, then the main program is already
-    // loaded by the linux kernel and we want to use it. on redox, we treat it
-    // the same.
+
+    let (path, name) = match resolve_path_name(&name_or_path, &envs) {
+        Some((p, n)) => (p, n),
+        None => {
+            eprintln!("ld.so: failed to locate '{}'", name_or_path);
+            unistd::_exit(1);
+            loop {}
+        }
+    };
+
+    // 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 program = {
         let mut pr = None;
         if !is_manual && cfg!(not(target_os = "redox")) {