fix(ld.so): do not depend on TLS at all
In the next big refactor (next PR), all of the platform functionality used by both relibc and ld.so will be moved into a `platform`/`sysdeps` crate and then ld.so would be moved out of relibc and not link with it. I think doing it in a seperate PR would make it more managable, as when I did half of it, the diff was pretty huge and that way it would be easier to review too :) Signed-off-by: Anhad Singh <andypython@protonmail.com>
This commit is contained in:
@@ -200,7 +200,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) --no-relax -T ld_so/ld_script/$(TARGET).ld --allow-multiple-definition --gc-sections --gc-keep-exported $^ -o $@
|
||||
$(LD) --no-relax -T ld_so/ld_script/$(TARGET).ld --allow-multiple-definition --gc-sections $^ -o $@
|
||||
|
||||
# Release targets
|
||||
|
||||
@@ -240,7 +240,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) --no-relax -T ld_so/ld_script/$(TARGET).ld --allow-multiple-definition --gc-sections --gc-keep-exported $^ -o $@
|
||||
$(LD) --no-relax -T ld_so/ld_script/$(TARGET).ld --allow-multiple-definition --gc-sections $^ -o $@
|
||||
|
||||
# Other targets
|
||||
|
||||
|
||||
@@ -98,25 +98,25 @@ SECTIONS
|
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
|
||||
/* Thread Local Storage sections */
|
||||
.tdata :
|
||||
/* .tdata :
|
||||
{
|
||||
PROVIDE_HIDDEN (__tdata_start = .);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
}
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } */
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
}
|
||||
.init_array :
|
||||
/* .init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
}
|
||||
} */
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
@@ -241,5 +241,16 @@ SECTIONS
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
|
||||
/DISCARD/ : {
|
||||
*(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*)
|
||||
/*
|
||||
* XXX: As of now, ld.so links with relibc which has the main functionality. In the next refactor,
|
||||
* ld.so will be moved out of relibc. So, till that time, we have to discard any sections
|
||||
* that may reference use thread local storage.
|
||||
*
|
||||
* .init_array also depends on TLS and is discarded as we don't need it.
|
||||
*/
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon)
|
||||
*(.init_array)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,25 +98,25 @@ SECTIONS
|
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
|
||||
/* Thread Local Storage sections */
|
||||
.tdata :
|
||||
/* .tdata :
|
||||
{
|
||||
PROVIDE_HIDDEN (__tdata_start = .);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
}
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } */
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
}
|
||||
.init_array :
|
||||
/* .init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
}
|
||||
} */
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
@@ -241,5 +241,16 @@ SECTIONS
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
|
||||
/DISCARD/ : {
|
||||
*(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*)
|
||||
/*
|
||||
* XXX: As of now, ld.so links with relibc which has the main functionality. In the next refactor,
|
||||
* ld.so will be moved out of relibc. So, till that time, we have to discard any sections
|
||||
* that may reference use thread local storage.
|
||||
*
|
||||
* .init_array also depends on TLS and is discarded as we don't need it.
|
||||
*/
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon)
|
||||
*(.init_array)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,25 +89,25 @@ SECTIONS
|
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
|
||||
/* Thread Local Storage sections */
|
||||
.tdata :
|
||||
/* .tdata :
|
||||
{
|
||||
PROVIDE_HIDDEN (__tdata_start = .);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
}
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } */
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
}
|
||||
.init_array :
|
||||
/* .init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
}
|
||||
} */
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
@@ -232,5 +232,16 @@ SECTIONS
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
|
||||
/DISCARD/ : {
|
||||
*(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*)
|
||||
/*
|
||||
* XXX: As of now, ld.so links with relibc which has the main functionality. In the next refactor,
|
||||
* ld.so will be moved out of relibc. So, till that time, we have to discard any sections
|
||||
* that may reference use thread local storage.
|
||||
*
|
||||
* .init_array also depends on TLS and is discarded as we don't need it.
|
||||
*/
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon)
|
||||
*(.init_array)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,27 +101,25 @@ SECTIONS
|
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
|
||||
/* Thread Local Storage sections */
|
||||
__relibc_ldso_tls_start = .;
|
||||
.tdata : ALIGN(4K)
|
||||
/* .tdata : ALIGN(4K)
|
||||
{
|
||||
PROVIDE_HIDDEN (__tdata_start = .);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
}
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
|
||||
__relibc_ldso_tls_end = .;
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } */
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
}
|
||||
.init_array :
|
||||
/* .init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
}
|
||||
} */
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
@@ -246,5 +244,16 @@ SECTIONS
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
|
||||
/DISCARD/ : {
|
||||
*(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*)
|
||||
/*
|
||||
* XXX: As of now, ld.so links with relibc which has the main functionality. In the next refactor,
|
||||
* ld.so will be moved out of relibc. So, till that time, we have to discard any sections
|
||||
* that may reference use thread local storage.
|
||||
*
|
||||
* .init_array also depends on TLS and is discarded as we don't need it.
|
||||
*/
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon)
|
||||
*(.init_array)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,27 +98,25 @@ SECTIONS
|
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
|
||||
/* Thread Local Storage sections */
|
||||
__relibc_ldso_tls_start = .;
|
||||
.tdata : ALIGN(4K)
|
||||
/* .tdata : ALIGN(4K)
|
||||
{
|
||||
PROVIDE_HIDDEN (__tdata_start = .);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
}
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
|
||||
__relibc_ldso_tls_end = .;
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } */
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
}
|
||||
.init_array :
|
||||
/* .init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
}
|
||||
} */
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
@@ -243,5 +241,16 @@ SECTIONS
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
|
||||
/DISCARD/ : {
|
||||
*(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*)
|
||||
/*
|
||||
* XXX: As of now, ld.so links with relibc which has the main functionality. In the next refactor,
|
||||
* ld.so will be moved out of relibc. So, till that time, we have to discard any sections
|
||||
* that may reference use thread local storage.
|
||||
*
|
||||
* .init_array also depends on TLS and is discarded as we don't need it.
|
||||
*/
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon)
|
||||
*(.init_array)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -45,8 +45,6 @@ _start:
|
||||
# Call ld_so_start(stack, entry)
|
||||
mov rdi, rbp
|
||||
sub rsi, 5
|
||||
lea rdx, __relibc_ldso_tls_start
|
||||
lea rcx, __relibc_ldso_tls_end
|
||||
call relibc_ld_so_start
|
||||
|
||||
# Restore original stack, clear registers, and jump to new start function
|
||||
@@ -83,7 +81,7 @@ pub unsafe extern "C" fn main(_argc: isize, _argv: *const *const i8) -> usize {
|
||||
|
||||
#[linkage = "weak"]
|
||||
#[no_mangle]
|
||||
extern "C" fn relibc_panic(pi: &::core::panic::PanicInfo) -> ! {
|
||||
extern "C" fn relibc_panic(_pi: &::core::panic::PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
|
||||
@@ -989,7 +989,7 @@ pub extern "C" fn herror(prefix: *const c_char) {
|
||||
str::from_utf8_unchecked(msg_cstr.to_bytes())
|
||||
};
|
||||
|
||||
let mut writer = platform::FileWriter(2);
|
||||
let mut writer = platform::FileWriter::new(2);
|
||||
// Prefix is optional
|
||||
match unsafe { CStr::from_nullable_ptr(prefix) }
|
||||
.and_then(|prefix| str::from_utf8(prefix.to_bytes()).ok())
|
||||
|
||||
@@ -852,7 +852,7 @@ pub unsafe extern "C" fn perror(s: *const c_char) {
|
||||
} else {
|
||||
"Unknown error"
|
||||
};
|
||||
let mut w = platform::FileWriter(2);
|
||||
let mut w = platform::FileWriter::new(2);
|
||||
|
||||
// The prefix, `s`, is optional (empty or NULL) according to the spec
|
||||
match CStr::from_nullable_ptr(s).and_then(|s_cstr| str::from_utf8(s_cstr.to_bytes()).ok()) {
|
||||
|
||||
+6
-13
@@ -5,7 +5,7 @@ use super::{
|
||||
};
|
||||
use crate::{
|
||||
header::{errno::STR_ERROR, sys_mman},
|
||||
platform::{types::c_void, ERRNO},
|
||||
platform::{types::c_void, Pal, Sys, ERRNO},
|
||||
};
|
||||
use alloc::{
|
||||
collections::BTreeMap,
|
||||
@@ -215,7 +215,7 @@ impl DSO {
|
||||
flags |= sys_mman::MAP_FIXED_NOREPLACE;
|
||||
}
|
||||
trace!(" mmap({:#x}, {:x}, {:x})", start, size, flags);
|
||||
let ptr = sys_mman::mmap(
|
||||
let ptr = Sys::mmap(
|
||||
start as *mut c_void,
|
||||
size,
|
||||
//TODO: Make it possible to not specify PROT_EXEC on Redox
|
||||
@@ -223,16 +223,9 @@ impl DSO {
|
||||
flags,
|
||||
-1,
|
||||
0,
|
||||
);
|
||||
if ptr as usize == !0
|
||||
/* MAP_FAILED */
|
||||
{
|
||||
return Err(Error::Malformed(format!(
|
||||
"failed to map {}. errno: {}",
|
||||
path,
|
||||
STR_ERROR[ERRNO.get() as usize]
|
||||
)));
|
||||
}
|
||||
)
|
||||
.map_err(|e| Error::Malformed(format!("failed to map {}. errno: {}", path, e.0)))?;
|
||||
|
||||
if start as *mut c_void != ptr::null_mut() {
|
||||
assert_eq!(
|
||||
ptr, start as *mut c_void,
|
||||
@@ -425,7 +418,7 @@ impl DSO {
|
||||
impl Drop for DSO {
|
||||
fn drop(&mut self) {
|
||||
self.run_fini();
|
||||
unsafe { sys_mman::munmap(self.mmap.as_mut_ptr() as *mut c_void, self.mmap.len()) };
|
||||
unsafe { Sys::munmap(self.mmap.as_mut_ptr() as *mut c_void, self.mmap.len()) };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+29
-12
@@ -12,14 +12,17 @@ use goblin::{
|
||||
|
||||
use crate::{
|
||||
c_str::{CStr, CString},
|
||||
fs::File,
|
||||
error::Errno,
|
||||
header::{
|
||||
dl_tls::{__tls_get_addr, dl_tls_index},
|
||||
fcntl, sys_mman,
|
||||
unistd::F_OK,
|
||||
},
|
||||
io::Read,
|
||||
platform::types::c_void,
|
||||
io::{self, Read},
|
||||
platform::{
|
||||
types::{c_int, c_void},
|
||||
Pal, Sys,
|
||||
},
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -31,6 +34,26 @@ use super::{
|
||||
ExpectTlsFree, PATH_SEP,
|
||||
};
|
||||
|
||||
/// Same as [`crate::fs::File`], but does not touch [`crate::platform::ERRNO`] as the dynamic
|
||||
/// linker does not have thread-local storage.
|
||||
struct File {
|
||||
fd: c_int,
|
||||
}
|
||||
|
||||
impl File {
|
||||
pub fn open(path: CStr, oflag: c_int) -> core::result::Result<Self, Errno> {
|
||||
Ok(Self {
|
||||
fd: Sys::open(path, oflag, 0)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Read for File {
|
||||
fn read(&mut self, buf: &mut [u8]) -> core::result::Result<usize, io::Error> {
|
||||
Sys::read(self.fd, buf).map_err(|err| io::Error::from_raw_os_error(err.0))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Symbol {
|
||||
pub value: usize,
|
||||
@@ -70,7 +93,6 @@ impl Linker {
|
||||
}
|
||||
}
|
||||
|
||||
/// **Warning**: Switches to the program's TCB. Thread locals should not be accessed after this.
|
||||
pub fn load_program(&mut self, path: &str, base_addr: Option<usize>) -> Result<usize> {
|
||||
self.load_object(path, &None, base_addr, false)?;
|
||||
return Ok(self.objects.get(&root_id).unwrap().entry_point);
|
||||
@@ -193,10 +215,7 @@ impl Linker {
|
||||
tcb.append_masters(tcb_masters);
|
||||
// Copy the master data into the static TLS block.
|
||||
tcb.copy_masters()?;
|
||||
|
||||
tcb.activate();
|
||||
// XXX: Beyond this point, any thread local's for ld.so should not be accessed. Though, the
|
||||
// TCB can still be accessed.
|
||||
} else {
|
||||
let tcb = Tcb::current().expect("failed to get current tcb");
|
||||
|
||||
@@ -502,12 +521,10 @@ impl Linker {
|
||||
vaddr as *const u8
|
||||
};
|
||||
trace!(" prot {:#x}, {:#x}: {:p}, {:#x}", vaddr, vsize, ptr, prot);
|
||||
sys_mman::mprotect(ptr as *mut c_void, vsize, prot)
|
||||
Sys::mprotect(ptr as *mut c_void, vsize, prot).map_err(|_| {
|
||||
Error::Malformed(format!("failed to mprotect {}", obj.name))
|
||||
})?;
|
||||
};
|
||||
|
||||
if res < 0 {
|
||||
return Err(Error::Malformed(format!("failed to mprotect {}", obj.name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-23
@@ -144,12 +144,6 @@ fn resolve_path_name(
|
||||
None
|
||||
}
|
||||
|
||||
static mut LDSO_MASTER: Master = Master {
|
||||
ptr: core::ptr::null_mut(),
|
||||
len: 0,
|
||||
offset: 0,
|
||||
};
|
||||
|
||||
// TODO: Make unsafe
|
||||
#[no_mangle]
|
||||
pub extern "C" fn relibc_ld_so_start(
|
||||
@@ -158,24 +152,9 @@ pub extern "C" fn relibc_ld_so_start(
|
||||
self_tls_start: usize,
|
||||
self_tls_end: usize,
|
||||
) -> usize {
|
||||
// Setup TLS and TCB for ourselves.
|
||||
//
|
||||
// On Redox, we need the TCB to setup in order to do anything. Also, thread local's like
|
||||
// ERRNO may be accessed by the dynamic linker, so we need static TLS to be setup.
|
||||
// Setup TCB for ourselves.
|
||||
unsafe {
|
||||
let tls_size = (self_tls_end - self_tls_start).next_multiple_of(4096); // alignment set in linker script
|
||||
|
||||
let tcb = Tcb::new(tls_size).expect_notls("ld.so: failed to allocate bootstrap TCB");
|
||||
|
||||
LDSO_MASTER.ptr = self_tls_start as *mut u8;
|
||||
LDSO_MASTER.len = self_tls_end - self_tls_start;
|
||||
LDSO_MASTER.offset = tls_size;
|
||||
|
||||
tcb.masters_ptr = &mut LDSO_MASTER;
|
||||
tcb.masters_len = core::mem::size_of::<Master>();
|
||||
|
||||
tcb.copy_masters()
|
||||
.expect_notls("ld.so: failed to copy TLS master data");
|
||||
let tcb = Tcb::new(0).expect_notls("ld.so: failed to allocate bootstrap TCB");
|
||||
tcb.activate();
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
|
||||
+4
-7
@@ -241,19 +241,16 @@ impl Tcb {
|
||||
|
||||
/// Mapping with correct flags for TCB and TLS
|
||||
unsafe fn map(size: usize) -> Result<&'static mut [u8]> {
|
||||
let ptr = sys_mman::mmap(
|
||||
let ptr = Sys::mmap(
|
||||
ptr::null_mut(),
|
||||
size,
|
||||
sys_mman::PROT_READ | sys_mman::PROT_WRITE,
|
||||
sys_mman::MAP_ANONYMOUS | sys_mman::MAP_PRIVATE,
|
||||
-1,
|
||||
0,
|
||||
);
|
||||
if ptr as usize == !0
|
||||
/* MAP_FAILED */
|
||||
{
|
||||
return Err(Error::Malformed(format!("failed to map tls")));
|
||||
}
|
||||
)
|
||||
.map_err(|_| Error::Malformed(format!("failed to map tls")))?;
|
||||
|
||||
ptr::write_bytes(ptr as *mut u8, 0, size);
|
||||
Ok(slice::from_raw_parts_mut(ptr as *mut u8, size))
|
||||
}
|
||||
|
||||
+3
-3
@@ -78,7 +78,7 @@ static ALLOCATOR: Allocator = NEWALLOCATOR;
|
||||
pub extern "C" fn relibc_panic(pi: &::core::panic::PanicInfo) -> ! {
|
||||
use core::fmt::Write;
|
||||
|
||||
let mut w = platform::FileWriter(2);
|
||||
let mut w = platform::FileWriter::new(2);
|
||||
let _ = w.write_fmt(format_args!("RELIBC PANIC: {}\n", pi));
|
||||
|
||||
Sys::exit(1);
|
||||
@@ -105,7 +105,7 @@ pub extern "C" fn rust_eh_personality() {}
|
||||
pub extern "C" fn rust_oom(layout: ::core::alloc::Layout) -> ! {
|
||||
use core::fmt::Write;
|
||||
|
||||
let mut w = platform::FileWriter(2);
|
||||
let mut w = platform::FileWriter::new(2);
|
||||
let _ = w.write_fmt(format_args!(
|
||||
"RELIBC OOM: {} bytes aligned to {} bytes\n",
|
||||
layout.size(),
|
||||
@@ -122,7 +122,7 @@ pub extern "C" fn rust_oom(layout: ::core::alloc::Layout) -> ! {
|
||||
pub extern "C" fn _Unwind_Resume() -> ! {
|
||||
use core::fmt::Write;
|
||||
|
||||
let mut w = platform::FileWriter(2);
|
||||
let mut w = platform::FileWriter::new(2);
|
||||
let _ = w.write_str("_Unwind_Resume\n");
|
||||
|
||||
Sys::exit(1);
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@ macro_rules! c_str {
|
||||
macro_rules! print {
|
||||
($($arg:tt)*) => ({
|
||||
use core::fmt::Write;
|
||||
let _ = write!($crate::platform::FileWriter(1), $($arg)*);
|
||||
let _ = write!($crate::platform::FileWriter::new(1), $($arg)*);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ macro_rules! println {
|
||||
macro_rules! eprint {
|
||||
($($arg:tt)*) => ({
|
||||
use core::fmt::Write;
|
||||
let _ = write!($crate::platform::FileWriter(2), $($arg)*);
|
||||
let _ = write!($crate::platform::FileWriter::new(2), $($arg)*);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+12
-6
@@ -1,7 +1,7 @@
|
||||
//! Platform abstractions and environment.
|
||||
|
||||
use crate::{
|
||||
error::ResultExt,
|
||||
error::{Errno, ResultExt},
|
||||
io::{self, Read, Write},
|
||||
};
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
@@ -86,13 +86,19 @@ impl<'a, W: WriteByte> WriteByte for &'a mut W {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FileWriter(pub c_int);
|
||||
pub struct FileWriter(pub c_int, Option<Errno>);
|
||||
|
||||
impl FileWriter {
|
||||
pub fn write(&mut self, buf: &[u8]) -> isize {
|
||||
Sys::write(self.0, buf)
|
||||
.map(|u| u as isize)
|
||||
.or_minus_one_errno()
|
||||
pub fn new(fd: c_int) -> Self {
|
||||
Self(fd, None)
|
||||
}
|
||||
|
||||
pub fn write(&mut self, buf: &[u8]) -> fmt::Result {
|
||||
let _ = Sys::write(self.0, buf).map_err(|err| {
|
||||
self.1 = Some(err);
|
||||
fmt::Error
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user