Skip to content

TCB Initialization issues if compiled with Relibc Debug Profile

To reproduce:

touch relibc
REPO_DEBUG=1 make prefix cr.zsh p.zsh # make sure zsh is statically linked

It will create a page fault without even touching the C main function. This happens both with GDB attached or not attached.

ser:~$ zsh
Page fault: 00007FFFFFEFFFC8 WR | US
RFLAG: 0000000000000202
CS:    000000000000002b
RIP:   00000000005a00ec
RSP:   00007fffffefffd0

I don't understand what is going on, but I can give clues: It stopped within relibc_start_v1, at:

// Initialize TLS, if necessary
    ld_so::init(
        sp,
        #[cfg(target_os = "redox")]
        thr_fd,
    );

Then it calls static_init, Tcb::new(vsize) then Self::os_new. Here's the values:

Screenshot_2025-09-21_21-50-14

While it's return Ok (with tcb zero??), it doesn't hit the next step of the call, it just going straight into the end of this function:

    /// Create a new TCB
    ///
    /// `size` is the size of the TLS in bytes.
    pub unsafe fn new(size: usize) -> Result<&'static mut Self, DlError> {
        let page_size = Sys::getpagesize();
        let (_abi_page, tls, tcb_page) = Self::os_new(size.next_multiple_of(page_size))?; <---- last called here

        let tcb_ptr = tcb_page.as_mut_ptr() as *mut Self;
        ptr::write(
            tcb_ptr,
            Self {
                   .....
            },
        );

        Ok(&mut *tcb_ptr)
    } // <------- next step going here

Then jumps at this panic function:

Screenshot_2025-09-21_21-40-34

I knew that you cannot print anything before TCB is inited, it will create page fault. I don't know why the Error values is DlError, but coincidentally, the enum value is zero, so something else trigger it.