Merge branch 'no-tcb' into 'master'
Handle panic without TCB See merge request redox-os/relibc!1530
This commit is contained in:
@@ -98,36 +98,3 @@ impl<Os> GenericTcb<Os> {
|
||||
unsafe { Some(&mut *Self::current_ptr()?) }
|
||||
}
|
||||
}
|
||||
pub fn panic_notls(_msg: impl core::fmt::Display) -> ! {
|
||||
// TODO: actually print _msg, perhaps by having panic_notls take a `T: DebugBackend` that can
|
||||
// propagate until called by e.g. relibc start
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
|
||||
pub trait ExpectTlsFree {
|
||||
type Unwrapped;
|
||||
|
||||
fn expect_notls(self, msg: &str) -> Self::Unwrapped;
|
||||
}
|
||||
impl<T, E: core::fmt::Debug> ExpectTlsFree for Result<T, E> {
|
||||
type Unwrapped = T;
|
||||
|
||||
fn expect_notls(self, msg: &str) -> T {
|
||||
match self {
|
||||
Ok(t) => t,
|
||||
Err(err) => panic_notls(format_args!(
|
||||
"{msg}: expect failed for Result with err: {err:?}",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> ExpectTlsFree for Option<T> {
|
||||
type Unwrapped = T;
|
||||
|
||||
fn expect_notls(self, msg: &str) -> T {
|
||||
match self {
|
||||
Some(t) => t,
|
||||
None => panic_notls(format_args!("{msg}: expect failed for Option")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-8
@@ -6,8 +6,6 @@
|
||||
|
||||
use core::cell::UnsafeCell;
|
||||
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
|
||||
use generic_rt::ExpectTlsFree; // not used on aarch64 or riscv64
|
||||
use generic_rt::GenericTcb;
|
||||
use redox_protocols::protocol::ProcMeta;
|
||||
use syscall::Sigcontrol;
|
||||
@@ -94,13 +92,13 @@ pub unsafe fn tcb_activate(tcb: &RtTcb, tls_end: usize, _tls_len: usize) {
|
||||
let mut env = syscall::EnvRegisters::default();
|
||||
|
||||
let file_fd = crate::sys::dup_into_upper_raw(tcb.thread_fd().as_raw_fd(), b"regs/env")
|
||||
.expect_notls("failed to open handle for process registers");
|
||||
.expect("failed to open handle for process registers");
|
||||
|
||||
syscall::read(file_fd, &mut env).expect_notls("failed to read gsbase");
|
||||
syscall::read(file_fd, &mut env).expect("failed to read gsbase");
|
||||
|
||||
env.gsbase = tls_end as u32;
|
||||
|
||||
syscall::write(file_fd, &env).expect_notls("failed to write gsbase");
|
||||
syscall::write(file_fd, &env).expect("failed to write gsbase");
|
||||
|
||||
let _ = crate::sys::close_raw(file_fd);
|
||||
|
||||
@@ -114,13 +112,13 @@ pub unsafe fn tcb_activate(tcb: &RtTcb, tls_end_and_tcb_start: usize, _tls_len:
|
||||
let mut env = syscall::EnvRegisters::default();
|
||||
|
||||
let file_fd = crate::sys::dup_into_upper_raw(tcb.thread_fd().as_raw_fd(), b"regs/env")
|
||||
.expect_notls("failed to open handle for process registers");
|
||||
.expect("failed to open handle for process registers");
|
||||
|
||||
syscall::read(file_fd, &mut env).expect_notls("failed to read fsbase");
|
||||
syscall::read(file_fd, &mut env).expect("failed to read fsbase");
|
||||
|
||||
env.fsbase = tls_end_and_tcb_start as u64;
|
||||
|
||||
syscall::write(file_fd, &env).expect_notls("failed to write fsbase");
|
||||
syscall::write(file_fd, &env).expect("failed to write fsbase");
|
||||
|
||||
let _ = crate::sys::close_raw(file_fd);
|
||||
|
||||
|
||||
@@ -541,7 +541,7 @@ pub struct TmpDisableSignalsGuard {
|
||||
active: bool,
|
||||
}
|
||||
|
||||
/// Used to prevent EINTR from appearing across all syscall
|
||||
/// Used to disable jumping to signal handler while the guard active
|
||||
pub fn tmp_disable_signals() -> TmpDisableSignalsGuard {
|
||||
if !crate::TLS_ACTIVATED.load(Ordering::Relaxed) {
|
||||
return TmpDisableSignalsGuard { active: false };
|
||||
|
||||
+10
-13
@@ -28,8 +28,6 @@ pub mod linker;
|
||||
pub mod start;
|
||||
pub mod tcb;
|
||||
|
||||
pub use generic_rt::{ExpectTlsFree, panic_notls};
|
||||
|
||||
static mut STATIC_TCB_MASTER: Master = Master {
|
||||
ptr: ptr::null_mut(),
|
||||
image_size: 0,
|
||||
@@ -66,9 +64,9 @@ fn static_init(
|
||||
auxv = unsafe { auxv.add(1) };
|
||||
}
|
||||
|
||||
let phdr = phdr_opt.expect_notls("failed to find AT_PHDR");
|
||||
let phent = phent_opt.expect_notls("failed to find AT_PHENT");
|
||||
let phnum = phnum_opt.expect_notls("failed to find AT_PHNUM");
|
||||
let phdr = phdr_opt.expect("failed to find AT_PHDR");
|
||||
let phent = phent_opt.expect("failed to find AT_PHENT");
|
||||
let phnum = phnum_opt.expect("failed to find AT_PHNUM");
|
||||
|
||||
for i in 0..phnum {
|
||||
let ph_addr = phdr + phent * i;
|
||||
@@ -95,7 +93,7 @@ fn static_init(
|
||||
ph.p_vaddr(endian) as usize,
|
||||
)
|
||||
},
|
||||
_ => panic_notls(format_args!("unknown AT_PHENT size {}", phent)),
|
||||
_ => panic!("unknown AT_PHENT size {}", phent),
|
||||
};
|
||||
|
||||
let page_size = Sys::getpagesize();
|
||||
@@ -115,11 +113,10 @@ fn static_init(
|
||||
STATIC_TCB_MASTER.image_size = p_filesz;
|
||||
STATIC_TCB_MASTER.offset = valign;
|
||||
|
||||
let tcb = Tcb::new(vsize).expect_notls("failed to allocate TCB");
|
||||
let tcb = Tcb::new(vsize).expect("failed to allocate TCB");
|
||||
tcb.masters_ptr = ptr::addr_of_mut!(STATIC_TCB_MASTER);
|
||||
tcb.masters_len = mem::size_of::<Master>();
|
||||
tcb.copy_masters()
|
||||
.expect_notls("failed to copy TLS master data");
|
||||
tcb.copy_masters().expect("failed to copy TLS master data");
|
||||
tcb.activate(
|
||||
#[cfg(target_os = "redox")]
|
||||
Some(thr_fd),
|
||||
@@ -160,9 +157,9 @@ pub unsafe fn init(
|
||||
{
|
||||
let file = thr_fd
|
||||
.dup_into_upper(b"regs/env")
|
||||
.expect_notls("failed to open handle for process registers");
|
||||
.expect("failed to open handle for process registers");
|
||||
|
||||
file.read(&mut env).expect_notls("failed to read gsbase");
|
||||
file.read(&mut env).expect("failed to read gsbase");
|
||||
}
|
||||
|
||||
tp = env.gsbase as usize;
|
||||
@@ -174,9 +171,9 @@ pub unsafe fn init(
|
||||
{
|
||||
let file = thr_fd
|
||||
.dup_into_upper(b"regs/env")
|
||||
.expect_notls("failed to open handle for process registers");
|
||||
.expect("failed to open handle for process registers");
|
||||
|
||||
file.read(&mut env).expect_notls("failed to read fsbase");
|
||||
file.read(&mut env).expect("failed to read fsbase");
|
||||
}
|
||||
|
||||
tp = env.fsbase as usize;
|
||||
|
||||
+14
-16
@@ -41,8 +41,6 @@ use super::{
|
||||
tcb::Tcb,
|
||||
};
|
||||
|
||||
use generic_rt::ExpectTlsFree;
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub const SIZEOF_EHDR: usize = 52;
|
||||
|
||||
@@ -192,13 +190,13 @@ pub unsafe extern "C" fn relibc_ld_so_start(
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
let at_phdr = at_phdr.expect("`AT_PHDR` must be present");
|
||||
let at_phnum = at_phnum.expect("`AT_PHNUM` must be present if `AT_PHDR` is");
|
||||
let at_phent = at_phent.expect("`AT_PHENT` must be present if `AT_PHDR` is");
|
||||
assert!(!at_phdr.is_null() && at_phnum != 0 && at_phent == size_of::<ProgramHeader>());
|
||||
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_entry = at_entry.expect("`AT_ENTRY` must be present");
|
||||
let at_base = at_base.unwrap_or_default();
|
||||
|
||||
let self_base = if at_base != 0 {
|
||||
@@ -252,7 +250,7 @@ pub unsafe extern "C" fn relibc_ld_so_start(
|
||||
base_addr: usize,
|
||||
) -> &'a [T] {
|
||||
if let Some(ptr) = ptr {
|
||||
let len = len.expect_notls("dynamic entry was present without it's corresponding size");
|
||||
let len = len.expect("dynamic entry was present without it's corresponding size");
|
||||
unsafe { core::slice::from_raw_parts(ptr.byte_add(base_addr), len) }
|
||||
} else {
|
||||
&[]
|
||||
@@ -315,7 +313,7 @@ fn stage2(
|
||||
let auxv = sp.auxv().cast();
|
||||
#[cfg(target_os = "redox")]
|
||||
let thr_fd = crate::platform::get_auxv_raw(auxv, redox_rt::auxv_defs::AT_REDOX_THR_FD)
|
||||
.expect_notls("no thread fd present");
|
||||
.expect("no thread fd present");
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
{
|
||||
@@ -324,43 +322,43 @@ fn stage2(
|
||||
sp.auxv().cast(),
|
||||
redox_rt::auxv_defs::AT_REDOX_FILETABLE_FD,
|
||||
)
|
||||
.expect_notls("no filetable fd present");
|
||||
.expect("no filetable fd present");
|
||||
let filetable_guard = redox_rt::proc::FdGuard::new(filetable_fd)
|
||||
.to_upper()
|
||||
.expect_notls("failed to move filetable fd to upper table");
|
||||
.expect("failed to move filetable fd to upper table");
|
||||
*redox_rt::current_filetable() =
|
||||
redox_rt::sys::FdTbl::from_binary_fd(filetable_guard)
|
||||
.expect_notls("failed to initialize FILETABLE");
|
||||
.expect("failed to initialize FILETABLE");
|
||||
}
|
||||
}
|
||||
|
||||
let tcb = Tcb::new(0).expect_notls("[ld.so]: failed to allocate bootstrap TCB");
|
||||
let tcb = Tcb::new(0).expect("[ld.so]: failed to allocate bootstrap TCB");
|
||||
tcb.activate(
|
||||
#[cfg(target_os = "redox")]
|
||||
Some(
|
||||
redox_rt::proc::FdGuard::new(thr_fd)
|
||||
.to_upper()
|
||||
.expect_notls("failed to move thread fd to upper table"),
|
||||
.expect("failed to move thread fd to upper table"),
|
||||
),
|
||||
);
|
||||
#[cfg(target_os = "redox")]
|
||||
{
|
||||
let proc_fd =
|
||||
crate::platform::get_auxv_raw(auxv, redox_rt::auxv_defs::AT_REDOX_PROC_FD)
|
||||
.expect_notls("no proc fd present");
|
||||
.expect("no proc fd present");
|
||||
|
||||
let ns_fd = crate::platform::get_auxv_raw(auxv, redox_rt::auxv_defs::AT_REDOX_NS_FD)
|
||||
.filter(|&fd| fd != usize::MAX)
|
||||
.map(|fd| {
|
||||
redox_rt::proc::FdGuard::new(fd)
|
||||
.to_upper()
|
||||
.expect_notls("failed to move ns fd to upper table")
|
||||
.expect("failed to move ns fd to upper table")
|
||||
});
|
||||
|
||||
redox_rt::initialize(
|
||||
redox_rt::proc::FdGuard::new(proc_fd)
|
||||
.to_upper()
|
||||
.expect_notls("failed to move proc fd to upper table"),
|
||||
.expect("failed to move proc fd to upper table"),
|
||||
ns_fd,
|
||||
);
|
||||
redox_rt::signal::setup_sighandler(&tcb.os_specific, true);
|
||||
|
||||
+6
-26
@@ -48,6 +48,7 @@ pub mod io;
|
||||
pub mod iter;
|
||||
pub mod ld_so;
|
||||
pub mod out;
|
||||
pub mod panic;
|
||||
pub mod platform;
|
||||
pub mod pthread;
|
||||
pub mod raw_cell;
|
||||
@@ -59,21 +60,11 @@ use crate::platform::{Allocator, NEWALLOCATOR};
|
||||
#[global_allocator]
|
||||
static ALLOCATOR: Allocator = NEWALLOCATOR;
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn relibc_panic(pi: &::core::panic::PanicInfo) -> ! {
|
||||
use core::fmt::Write;
|
||||
|
||||
let mut w = platform::FileWriter::new(2);
|
||||
let _ = w.write_fmt(format_args!("RELIBC PANIC: {}\n", pi));
|
||||
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[panic_handler]
|
||||
#[linkage = "weak"]
|
||||
pub fn rust_begin_unwind(pi: &::core::panic::PanicInfo) -> ! {
|
||||
relibc_panic(pi)
|
||||
crate::panic::relibc_panic(pi)
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
@@ -87,17 +78,11 @@ pub extern "C" fn rust_eh_personality() {}
|
||||
#[allow(improper_ctypes_definitions)]
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn rust_oom(layout: ::core::alloc::Layout) -> ! {
|
||||
// Layout not FFI-safe?
|
||||
use core::fmt::Write;
|
||||
|
||||
let mut w = platform::FileWriter::new(2);
|
||||
let _ = w.write_fmt(format_args!(
|
||||
"RELIBC OOM: {} bytes aligned to {} bytes\n",
|
||||
panic!(
|
||||
"RELIBC OOM: {} bytes aligned to {} bytes",
|
||||
layout.size(),
|
||||
layout.align()
|
||||
));
|
||||
|
||||
core::intrinsics::abort();
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
@@ -105,10 +90,5 @@ pub extern "C" fn rust_oom(layout: ::core::alloc::Layout) -> ! {
|
||||
#[linkage = "weak"]
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn _Unwind_Resume() -> ! {
|
||||
use core::fmt::Write;
|
||||
|
||||
let mut w = platform::FileWriter::new(2);
|
||||
let _ = w.write_str("_Unwind_Resume\n");
|
||||
|
||||
core::intrinsics::abort();
|
||||
panic!("_Unwind_Resume")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
use core::fmt::Write;
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn relibc_panic(pi: &::core::panic::PanicInfo) -> ! {
|
||||
use core::fmt::Write;
|
||||
|
||||
let mut w = PanicWriter::new();
|
||||
let _ = w.write_fmt(format_args!("RELIBC PANIC: {}\n", pi));
|
||||
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
|
||||
struct PanicWriter;
|
||||
|
||||
impl PanicWriter {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for PanicWriter {
|
||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||
// Cannot use Sys::write, Tcb might not be available
|
||||
#[cfg(target_os = "redox")]
|
||||
{
|
||||
// TODO: init stderr ourself if it not ready.
|
||||
// Workaround: If stderr is not being prepared,
|
||||
// add debugging log at kernel write() syscall
|
||||
let _ = syscall::write(2, s.as_bytes());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Non-redox platforms can directly write to stderr
|
||||
let mut w = crate::platform::FileWriter::new(2);
|
||||
w.write_str(s)
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -13,7 +13,7 @@ use redox_rt::RtTcb;
|
||||
use crate::{
|
||||
error::Errno,
|
||||
header::{errno::*, pthread as header, sched::sched_param, sys_mman},
|
||||
ld_so::{ExpectTlsFree, tcb::Tcb},
|
||||
ld_so::tcb::Tcb,
|
||||
platform::{Pal, Sys, types::*},
|
||||
};
|
||||
|
||||
@@ -47,7 +47,7 @@ pub unsafe fn init() {
|
||||
thread.stack_size = STACK_SIZE;
|
||||
}
|
||||
|
||||
let current_tcb = unsafe { Tcb::current() }.expect_notls("no TCB present for main thread");
|
||||
let current_tcb = unsafe { Tcb::current() }.expect("no TCB present for main thread");
|
||||
current_tcb.pthread = thread;
|
||||
unsafe {
|
||||
current_tcb.pthread.tcb_selfref.get().write(current_tcb);
|
||||
@@ -221,7 +221,7 @@ unsafe extern "C" fn new_thread_shim(
|
||||
tcb: *mut Tcb,
|
||||
synchronization_mutex: *const Mutex<u64>,
|
||||
) -> ! {
|
||||
let tcb = unsafe { tcb.as_mut() }.expect_notls("non-null TLS is required");
|
||||
let tcb = unsafe { tcb.as_mut() }.expect("non-null TLS is required");
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
{
|
||||
|
||||
+5
-8
@@ -3,9 +3,6 @@
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
use core::{intrinsics, ptr};
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
use generic_rt::ExpectTlsFree;
|
||||
|
||||
use crate::{
|
||||
ALLOCATOR,
|
||||
header::{libgen, stdio, stdlib},
|
||||
@@ -169,10 +166,10 @@ pub unsafe extern "C" fn relibc_start_v1(
|
||||
unsafe {
|
||||
crate::platform::get_auxv_raw(sp.auxv().cast(), redox_rt::auxv_defs::AT_REDOX_THR_FD)
|
||||
}
|
||||
.expect_notls("no thread fd present"),
|
||||
.expect("no thread fd present"),
|
||||
)
|
||||
.to_upper()
|
||||
.expect_notls("failed to move thread fd to upper table");
|
||||
.expect("failed to move thread fd to upper table");
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
{
|
||||
@@ -183,12 +180,12 @@ pub unsafe extern "C" fn relibc_start_v1(
|
||||
redox_rt::auxv_defs::AT_REDOX_FILETABLE_FD,
|
||||
)
|
||||
}
|
||||
.expect_notls("no filetable fd present");
|
||||
.expect("no filetable fd present");
|
||||
let filetable_guard = redox_rt::proc::FdGuard::new(filetable_fd)
|
||||
.to_upper()
|
||||
.expect_notls("failed to move filetable fd to upper table");
|
||||
.expect("failed to move filetable fd to upper table");
|
||||
*redox_rt::current_filetable() = redox_rt::sys::FdTbl::from_binary_fd(filetable_guard)
|
||||
.expect_notls("failed to initialize FILETABLE");
|
||||
.expect("failed to initialize FILETABLE");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user