From c286ad2868a3ab59b234a91d44f09dc04ffbba0f Mon Sep 17 00:00:00 2001 From: Anhad Singh <andypython@protonmail.com> Date: Thu, 5 Dec 2024 23:03:52 +1100 Subject: [PATCH] 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> --- Makefile | 4 +- ld_so/ld_script/aarch64-unknown-redox.ld | 21 ++++++++--- ld_so/ld_script/i686-unknown-redox.ld | 21 ++++++++--- ld_so/ld_script/riscv64gc-unknown-redox.ld | 21 ++++++++--- ld_so/ld_script/x86_64-unknown-linux-gnu.ld | 23 ++++++++---- ld_so/ld_script/x86_64-unknown-redox.ld | 23 ++++++++---- ld_so/src/lib.rs | 4 +- src/header/netdb/mod.rs | 2 +- src/header/stdio/mod.rs | 2 +- src/ld_so/dso.rs | 19 +++------- src/ld_so/linker.rs | 41 +++++++++++++++------ src/ld_so/start.rs | 25 +------------ src/ld_so/tcb.rs | 11 ++---- src/lib.rs | 6 +-- src/macros.rs | 4 +- src/platform/mod.rs | 18 ++++++--- 16 files changed, 143 insertions(+), 102 deletions(-) diff --git a/Makefile b/Makefile index 2a734b50c..ca3737a68 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/ld_so/ld_script/aarch64-unknown-redox.ld b/ld_so/ld_script/aarch64-unknown-redox.ld index 1d08c36eb..b7ff6d7ed 100644 --- a/ld_so/ld_script/aarch64-unknown-redox.ld +++ b/ld_so/ld_script/aarch64-unknown-redox.ld @@ -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) + } } diff --git a/ld_so/ld_script/i686-unknown-redox.ld b/ld_so/ld_script/i686-unknown-redox.ld index f9badfd1d..8e4576a8d 100644 --- a/ld_so/ld_script/i686-unknown-redox.ld +++ b/ld_so/ld_script/i686-unknown-redox.ld @@ -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) + } } diff --git a/ld_so/ld_script/riscv64gc-unknown-redox.ld b/ld_so/ld_script/riscv64gc-unknown-redox.ld index 37fb2bb1e..cfbbc0cdf 100644 --- a/ld_so/ld_script/riscv64gc-unknown-redox.ld +++ b/ld_so/ld_script/riscv64gc-unknown-redox.ld @@ -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) + } } diff --git a/ld_so/ld_script/x86_64-unknown-linux-gnu.ld b/ld_so/ld_script/x86_64-unknown-linux-gnu.ld index c67cb55af..3aa0e0f47 100644 --- a/ld_so/ld_script/x86_64-unknown-linux-gnu.ld +++ b/ld_so/ld_script/x86_64-unknown-linux-gnu.ld @@ -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) + } } diff --git a/ld_so/ld_script/x86_64-unknown-redox.ld b/ld_so/ld_script/x86_64-unknown-redox.ld index 00df43509..975c833fb 100644 --- a/ld_so/ld_script/x86_64-unknown-redox.ld +++ b/ld_so/ld_script/x86_64-unknown-redox.ld @@ -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) + } } diff --git a/ld_so/src/lib.rs b/ld_so/src/lib.rs index 9ba54a23c..955d6b14c 100644 --- a/ld_so/src/lib.rs +++ b/ld_so/src/lib.rs @@ -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 {} } diff --git a/src/header/netdb/mod.rs b/src/header/netdb/mod.rs index d9d2f8103..e35a30fc3 100644 --- a/src/header/netdb/mod.rs +++ b/src/header/netdb/mod.rs @@ -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()) diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs index d94b5f1d6..22bd933b4 100644 --- a/src/header/stdio/mod.rs +++ b/src/header/stdio/mod.rs @@ -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()) { diff --git a/src/ld_so/dso.rs b/src/ld_so/dso.rs index 135ec59dc..b8322ba41 100644 --- a/src/ld_so/dso.rs +++ b/src/ld_so/dso.rs @@ -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()) }; } } diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index 998a3bdb7..9e15266c0 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -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))); - } } } diff --git a/src/ld_so/start.rs b/src/ld_so/start.rs index 67fb77081..5c695cf39 100644 --- a/src/ld_so/start.rs +++ b/src/ld_so/start.rs @@ -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")] diff --git a/src/ld_so/tcb.rs b/src/ld_so/tcb.rs index d26d4d0ae..8521842f4 100644 --- a/src/ld_so/tcb.rs +++ b/src/ld_so/tcb.rs @@ -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)) } diff --git a/src/lib.rs b/src/lib.rs index d2697004d..4b30d18fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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); diff --git a/src/macros.rs b/src/macros.rs index 23f6809d1..a7ef0c8e6 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -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)*); }); } diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 7d3ebc50c..92e3e042e 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -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(()) } } -- GitLab