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:
committed by
jD91mZM2
parent
d08c63b1e7
commit
40328a0d09
@@ -2,3 +2,5 @@
|
||||
prefix/
|
||||
sysroot/
|
||||
**/target/
|
||||
.gdb_history
|
||||
*.patch
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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")) {
|
||||
|
||||
Reference in New Issue
Block a user