Modify ld_script so that it works on linux.

Honestly, I have no idea why are these modifications needed, but it
seams they are needed
This commit is contained in:
Ahmed Abd El Mawgood
2020-08-12 10:19:32 +00:00
committed by jD91mZM2
parent d08c63b1e7
commit 40328a0d09
6 changed files with 95 additions and 31 deletions
+2
View File
@@ -2,3 +2,5 @@
prefix/
sysroot/
**/target/
.gdb_history
*.patch
+2 -2
View File
@@ -134,7 +134,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
@@ -173,7 +173,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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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")) {